【问题标题】:Command line arguments and read file/print text in C命令行参数和读取 C 中的文件/打印文本
【发布时间】:2015-02-14 05:23:08
【问题描述】:

我正在尝试使用命令行参数并在 C 中解析文本文件。基本上我希望能够输入两个数字,例如 1 和 4,并让它读取文本文件的一列然后打印它到标准输出。我希望能够这样做:

PID   TTY        TIME     CMD
449   ttys000    0:00.35 -bash
1129  ttys001    0:00.35 -bash
25605 ttys001    0:00.15  vi prog.c
6132  ttys002    0:00.11 -bash
6208  ttys002    0:00.03  vi test

然后做:

./your_prog 1 4 < data.txt 

PID CMD
449 bash
1129 -bash
25605 vi
6132 -bash 
6208 vi 

所以我需要输入我要打印的列,在“data.txt”中重定向文件并让它处理文件并像这样打印。

到目前为止,我的代码有这个:

 #include <stdio.h>
 int main(int argc, char **argv){
//int row = argc[0];
//int col = argc[1];
//if number entered is less than one, re-enter

int i;
for (i = 0; i < argc; i++) {
  printf("argv[%d] = %s\n", i, argv[i]);
}
if(argc < 1){
  fprintf(stderr, "Enter a valid input");

  //quit
  return 1;
} 
else{   
  char ch[256];
  //ch[255] = '\0';

    while(fgets(ch, 256, stdin) != NULL){
      printf("%s", ch);
    }
  } 
  return 1;
}

但不确定我是否走在正确的轨道上,并且对下一步该做什么感到困惑。我是 C 的新手,所以如果这是一个简单的问题,我深表歉意。

【问题讨论】:

  • 你似乎有一个好的开始,尤其是对于一个 C 新手来说。请注意,argv[0] 将是程序的名称。它的参数(如果有的话)将在argv[1] ... argv[argc - 1] 中呈现。
  • 虽然您正确使用了fgets(),但它确实将您限制在一个固定的最大行长度,并且它会在没有太多警告的情况下截断长行。如果您使用的是 GCC 和 GNU C 库,那么您可以考虑使用 getline() 函数。
  • 除非您打算假设固定的列宽,否则您必须以某种方式拆分行。如果您愿意假设列之间存在某种分隔符,例如空格,那么您可以通过标准 strtok() 函数将输入行分成列。但是请注意,示例输入的第 4 列中的某些值包含内部空格。

标签: c process command-line-arguments


【解决方案1】:

为了帮助您入门,这改进了您收集命令行信息的方式。注意第一个参数argv[0] 是可执行文件本身的名称。请记住上面的cmets,我没有进一步改进。语法是progname filename col1 col2

#include <stdio.h>
#include <stdlib.h>

void fatal(char *msg) {
    printf("%s\n", msg);
    exit (1);
}

int main(int argc, char*argv[])
{
    int col1, col2;
    FILE *fp;
    char ch[256];

    if(argc < 4)
        fatal("Need three arguments");

    if (sscanf(argv[2], "%d", &col1) != 1)
        fatal("Argument 1 error");

    if (sscanf(argv[3], "%d", &col2) != 1)
        fatal("Argument 2 error");

    printf("Read columns %d and %d from file %s\n", col1, col2, argv[1]);
    if ((fp = fopen(argv[1], "r")) == NULL)
        fatal("Unable to open file");

    // process the file
    while (fgets(ch, 256, fp) != NULL) {
        printf("%s", ch);
    }
    fclose(fp);
    return 0;
}

【讨论】:

  • 我遇到了上面代码显示的问题:if (sscanf(argv[2], "%d", &amp;col1) != 1) fatal("Argument 1 error"); 是将 argv[2] 设置为 col1 吗?
  • @ksudood 不,它是从argv[2] 设置col1。字符串指针数组argv[] 包含您在命令行中输入的参数,除了argv[0],这是您程序中的第一个循环显示的内容。 sscanf()和朋友返回扫描成功的字段数。
  • 好的,我设法让它打印出我的整个文本文件。你会如何建议我开始处理和挑选文件。就像我只想像这样打印 col1:PID 449 1129 25605 6132 6208
  • 阅读@JohnBollinger 的cmets,查找strtok() 并自己尝试一下。在他的一个评论中,他说您可能会丢失部分字段 - 但您确实在问题示例中显示部分字段。首先将所有字段分开并再次打印出来,然后再尝试选择您真正想要的字段。一步一步,轻松搞定。
  • 我已经得到了 strtok() 来解析我的文本文件。现在我将如何告诉它要打印哪些列?我将发布到目前为止的部分代码。
【解决方案2】:

这是我目前所拥有的。我可以让它解析然后我可以把它放回去,但是对于我的生活,我无法弄清楚如何告诉它只打印第一列。如果我可以有一些方向,那么我可以弄清楚如何做剩下的,但我可以找到任何东西。这是我到目前为止的代码:

#include <stdio.h>
#include <string.h>


int main(int argc, char **argv){
int col1, col2;
int size = 512;
char ch[size];
char *temp[size];

char *token;

if(argc == 1){
fprintf(stderr, "I need more!\n");
return 1;
}

else{
//test to see what is stored

  int i;
  for (i = 0; i < argc; i++) {
    printf("argv[%d] = %s\n", i, argv[i]);   
  }

  if(sscanf(argv[1], "%d", &col1) != 1) return 1;
  if(sscanf(argv[2], "%d", &col2) != 1) return 1;   

  while(fgets(ch, size, stdin) != NULL){
    //get 1st token
    token = strtok(ch, " ");
      while(token != NULL){
        printf(" %s", token);
        temp[i++] = token;
        token = strtok(NULL, " ");
      }   
    } 
    return 0;   
  }
}

【讨论】:

  • 只统计每行字段的个数,如果不是col1col2则忽略
最近更新 更多