【问题标题】:Comparing string from textfile in C比较C中文本文件中的字符串
【发布时间】:2019-09-22 03:38:48
【问题描述】:

我想比较字符串用户输入和文本文件中的字符串。

我正在比较 uname 的值和存储的当前值。它进入 while 循环,但是当它们匹配时,它不会进入 if 块,如果 storage 和 uname 具有相同的值,则该块应该进行测试。

void compare()
{
   char uname[20];
   FILE *list = fopen("list.txt","a");

   if(list == NULL)
   {
      printf("Textfile doesn't have any content\n");
   }

   printf("Enter username: ");
   scanf("%s",&uname);
   fprintf(list,"%s\n",uname);
   fclose(list);

   list = fopen("listahan.txt","r");

   char storage[50]; //storage of the string that I will get from the textfile

   if(list != NULL) //check if list have content
   {
       while((fgets(storage,sizeof(storage),list) != NULL)) //if list have content, get it line by line and compare it to the uname.
       {
          printf("storage:%s\n",storage); // for debug, checks the current value of storage
          printf("uname:%s\n",uname); //for debug, checks the value of uname

          if(storage == uname) //this if block is being ignored, even when the storage and uname match, the block does not execute.
          {
             printf("Login Success!\n");
          }
    }
}

【问题讨论】:

  • 我怀疑您从文件中读取的行尾可能有换行符!
  • 写一些类似 perl 的 chomp 的东西来从使用 fgets 读取的行尾删除 '\n' 或 '\r\n'。您还可以使用 fgets(storage,sizeof(storage),stdin) 后跟 chomp(storage) 和 strncpy(uname,storage,sizeof(uname)-10),而不是 scanf...
  • char uname[20];,见C11 Standard - 6.3.2.1 Other Operands - Lvalues, arrays, and function designators(p3)uname已经是一个指针,所以scanf("%s",&uname);中不需要&

标签: c


【解决方案1】:

输入字符数组时,无需指定&unameWhy doesn't scanf need an ampersand for strings and also works fine in printf (in C)?

改正为:

scanf("%s",uname);

剩余的更正:

if(list != NULL) //check if list have content
{
    while(fgets(storage,sizeof(storage),list) != NULL) //if list have content, get it line by line and compare it to the uname.
    {
        if (*storage == '\n') 
            continue;
        sscanf(storage, "%[^\n]", storage);
        printf("storage:%s\n",storage); // for debug, checks the current value of storage
        printf("uname:%s\n",uname); //for debug, checks the value of uname

        if(!strcmp(storage, uname)) //this if block is being ignored, even when the storage and uname match, the block does not execute.
        {
            printf("Login Success!\n");
        }
    }
}

另外,您可以简单地使用fscanf() 而不是fgets,但这是一个非常糟糕的主意,请阅读Trouble reading a line using fscanf() 中的第一个答案

所以首先你 fgets() 将价值存储在 storage 中。

manpage中所述:

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

简而言之,如果遇到换行符,读取将停止,但它也会被存储。

所以"username" != "username\n"。这就是为什么我们将 sscanf() 字符串再次转换为相同的字符串以读取直到 \n 为止。

还要比较字符数组,你需要使用strcmp()。如果您比较 char *== 会起作用。

【讨论】:

  • 您也可以简单地用storage[strcspn (storage, "\n")] = 0; 修剪'\n'。如果您使用sscanf(这很好),您确实需要检查退货,例如if (sscanf (..) != 1) { /* handle error */ } as fgets 会很高兴地读取一个只存储 '\n' 的空行,如果你不检查 sscanf 返回可能会让你大吃一惊。
  • @DavidC.Rankin,是否需要,因为如果storage 为空,strcmp 根本不会匹配并继续下一行。还有其他原因吗?谢谢。
  • 你是对的,不会有错误,你只会输出和比较一个可能不希望出现的 empty-string。您也可以在拨打fgets 之后立即检查if (*storage == '\n') continue;,然后再拨打sscanf
  • @DavidC.Rankin,有道理,我做了更改,谢谢。
【解决方案2】:

您正在比较存储数组的地址和 uname 数组的地址。它总是错误的。您必须在条件中使用 strcmp(storage,uname) 来比较两个数组的字符串。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-03-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多