Strcmp没有比较argv中的字符串

时间:2017-10-25 06:44:21

标签: c string argv strcmp

**更新时间为26/10 - >首先感谢大家的帮助,我现在越来越近了,我需要更多的工作和学习,但我真的很感谢你帮助了我很多:-)

还不知道为什么第一次"下雨" input.txt文件中的单词没有得到strcmp的正输出,而从cmd我可以看到"<"支架不会出现,但最后一条线是有效线路。

同时检查了来自Removing trailing newline character from fgets() input

的突出显示的回复

即使我将代码更改为以下内容:

while( fgets (line, sizeof line, fp)!=NULL ) {

  /* remove \n from at the end of the str buffer*/   
  char * pos;
  /*
  if ((pos = strchr(line, '\n')) != NULL)
     *pos = '\0';
  */
  line[strcspn(line, "\n")] = 0;

我得到的结果与我使用if块的结果相同。也许我会得到额外的\ 0,可能就是这种情况。任何人都有一个链接,我可以阅读我刚才使用的分隔符,或者调试器的一个很好的参考等等......我一看到这个就会看看它?非常感谢你!

read5.c version:现在从那个input.txt文件中,它在最后一次" rain"上有一个额外的空间。单词,我删除了空格,它能够找到并获得最后一个单词比较作为真实结果,在strcmp if块中运行。但那是唯一一个字符串,它是if if block的真正积极结果。

我可以看到cmd上的

$./read5 input.txt rain output.txt sun
>Maria
>rain
>manel
>Bla bla
<rain>
Found it! rain

在output.txt上,它变为:

Maria
rain
manel
Bla bla
sun

read5.c

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

/**
* Compile program:
*    gcc read3.c -o read3
*
*/
int main (int argc, char **argv) {
   FILE *fp, *fo;
   char *compare, *replace;
   char line[246];

   if (argc <= 4){
      printf(">Missing arguments on the command line.\n");
      printf(">Be sure you run the program as\n\"./read3 input.txt compare outout.txt replace\"\n\n");
   }

   /* opening file for reading */
   fp = fopen(argv[1] , "r");
   if(fp == NULL){
      perror("Error opening input file");
      return 1;
   }
   compare = argv[2];

   fo = fopen(argv[3], "w");
   if(fo == NULL){
      perror("Error opening output file");
      return 1;  //TODO check if: return 1 because it was expected, right?
   }
   replace = argv[4];

   /*
   printf(); made to test version 2
   //printf("We are going to compare %s\n", compare);
   //printf("We are going to replace it with %s\n", replace);
   */


   while( fgets (line, sizeof line, fp)!=NULL ) {

      /* remove \n from at the end of the str buffer*/   
      char * pos;
      if ((pos = strchr(line, '\n')) != NULL)
         *pos = '\0';

      /* print str enclosed in <> so we can see what str actually contains */
      //printf("Inside the loop, got the string: %s\n", line);

      //printing the strings with defined delimiters
      printf("<%s>\n", line);

      if(strcmp(compare, line) == 0){
         printf("Found it! %s \n", line);
         fprintf(fo, "%s\n", replace);
      }
      else{
         fprintf(fo, "%s\n", line);
      }

   }
   fclose(fp);
   fclose(fo);

   return 0;
}

第一个没有编辑的问题:25/10

我需要制作一个像这样运行的程序:

./read2 input.txt rain output.txt sun 

它会读取input.txt,搜索rain字符串,如果找到它,则将其替换为sun字符串,并输出input.txt中所有带有替换字符的文本output.txt

但是到目前为止我使用的代码,strcmp并没有比较我想要的字符串,也许它在命令行上有额外的空间,我不知道..现在正在做的是复制从input.txtoutput.txt的所有内容...它始终运行else块...

Read2.c

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

int main(int argc, char **argv) {
    FILE *fp, *fo;
    char str[60];

    //char* token;
    /* opening file for reading */
    fp = fopen(argv[1], "r");
    char *compare = argv[2];

    fo = fopen(argv[3], "w+");
    char *replace = argv[4];

    if (fp == NULL) {
        perror("Error opening file");
        return(-1);
    }

    //printf("We are going to compare %s\n", compare);

    //printf("We are going to replace it with %s\n", replace);

    while (fgets(str, 60, fp) != NULL) {
        /* writing content to stdout */
        //Take the \n out 
        //token = strtok(str, "\n");

        printf("Inside the loop, got the string: %s\n", str);
        if (strcmp(compare, str) == 0) {
            //puts(str);
            printf("Found it! %s \n", str);

            fprintf(fo, "%s", replace);
        } else {
            fprintf(fo, "%s", str);
        }
    }
    fclose(fp);

    return(0);
}

input.txt

Maria
rain
manel
Bla bla
rain 

Ouput.txt与input.txt完全相同,在它为空之前,所以代码正常工作,但使用strcmp进行测试的if块除外。

4 个答案:

答案 0 :(得分:1)

问题是\n缓冲区末尾的strfgets在其读取的行的末尾添加\n,您需要在比较之前删除它。

这就是你需要的:

  while (fgets(str, 60, fp) != NULL) {

    /* remove \n from at the end of the str buffer*/    
    char *pos;
    if ((pos = strchr(str, '\n')) != NULL)
      *pos = '\0';

    /* print str enclosed in <> so we can see what str actually contains */
    printf("Inside the loop, got the string: <%s>\n", str);

    if (strcmp(compare, str) == 0) {
      printf("Found it! %s\n", str);
      fprintf(fo, "%s\n", replace);
    }
    else {
      fprintf(fo, "%s\n", str);
    }
  }

查看代码中的注释以获得解释。

答案 1 :(得分:0)

您的方法失败,因为从输入文件中读取的行包含一个尾随换行符'\n',使得比较返回非零。

您可以在与搜索字符串进行比较之前剥离换行符。

请注意还有其他问题:

  • 您应该通过测试argc > 4来验证是否已经传递了足够的命令行参数。
  • 无需在更新模式下"w+"打开输出文件,"w"更简单,更好。
  • 对于行数组,60个字节有点小,将正确处理的最长行限制为58个字节。

以下是改进版本:

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

int main(int argc, char **argv) {
    FILE *fp, *fo;
    char *compare, *replace;
    char line[256];

    if (argc <= 4) {
        printf("missing command line arguments\n");
        return 1;
    }
    fp = fopen(argv[1], "r");
    if (fp == NULL) {
        perror("Error opening input file");
        return 1;
    }
    compare = argv[2];
    fo = fopen(argv[3], "w");
    if (fo == NULL) {
        perror("Error opening output file");
        return 1;
    }
    replace = argv[4];

    while (fgets(line, sizeof line, fp) != NULL) {
        line[strcspn(line, "\n")] = '\0';
        if (strcmp(line, compare) == 0) {
            printf("fount it!);
            fprintf(fo, "%s\n", replace);
        } else {
            fprintf(fo, "%s\n", line);
        }
    }
    fclose(fp);
    fclose(fo);

    return 0;
}

请注意,长行将被分成适合line数组的块,因此上述天真方法可能存在误报。

您可以使用此内循环完全删除此限制:

int c;
int pos = 0;
int cmplen = strlen(compare);
for (;;) {
    c = getc(fp);
    if (c == '\n' || c == EOF) {
        if (pos == cmplen) {
            fprintf(fo, "%s", replace);
        } else
        if (pos > 0) {
            fprintf(fo, "%*s", pos, compare);
        }
        pos = 0;
        if (c == EOF)
            break;
    } else {
        if (pos >= 0) {
            if (compare[pos] == (char)c) {
                pos++;
                continue;
            }
            if (pos > 0) {
                fprintf(fo, "%*s", pos, compare);
            }
            pos = -1;
        }
    }
    putc(c, fo);
}

答案 2 :(得分:0)

来自man fgets

  

char * fgets(char * s,int size,FILE * stream);

     

fgets()从流中读取最多一个小于大小的字符并将它们存储到指向的缓冲区中          由s。读数在EOF或换行符后停止。 如果读取换行符,则会将其存储到缓冲区中。 A.          终止空字节('\ 0')存储在缓冲区中的最后一个字符之后。

因此,您需要从缓冲区s中删除换行符,例如:

c[strlen(c) - 1] = 0 when c[strlen(c) - 1] == '\n'

答案 3 :(得分:0)

read.c

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

/**
* How to compile program:
*    gcc read.c -o read
*
* How to run the program: 
*      .> ./read input.txt rainy output.txt sunny
* (On Windows MinGW compiler, simply: 
*      .> read input.txt rainy output.txt sunny - without ./)
*
*/
int main (int argc, char **argv) {
   FILE *fp, *fo;
   char *compare, *replace;
   char line[246];

   if (argc <= 4){
      printf(">Missing arguments on the command line.\n");
      printf(">Be sure you run the program as\n\"./read input.txt compare outout.txt replace\"\n\n");
   }

   /* Opening files for reading */
   fp = fopen(argv[1] , "r");
   if(fp == NULL){
      perror("Error opening input file");
      return 1;
   }
   compare = argv[2];

   fo = fopen(argv[3], "w");
   if(fo == NULL){
      perror("Error opening output file");
      return 1; 
   }
   replace = argv[4];

   while( fgets (line, (sizeof line), fp)!=NULL ) {
      line[strcspn(line, "\n")] = 0;
       if(strcmp(compare, line) == 0){
         printf("Found it! %s \n", line);
         fprintf(fo, "%s\n", replace);
      }
      else{
         fprintf(fo, "%s\n", line);
      } 
   }
   fclose(fp);
   fclose(fo);
   return 0;
}

/* 
Important info

strcspn :: 
Locate first occurrence of character in string, 
after locating the first occurrence of \n, replaces it by 0.


Sources::
https://stackoverflow.com/questions/2693776/removing-trailing-newline-character-from-fgets-input/28462221#28462221

Used to debug:
.>printf("1st: Reads input.txt, removes '\\n' from fgets, and prints it \n");
.>printf("2nd: Compares each line with 'rainy' \n");


.>printf("<%s>\n", line);

*/

input.txt

cloudy
rainy
chilly
rainy
rainy