【问题标题】:Converting strings to uppercase to compare with user input in C将字符串转换为大写以与 C 中的用户输入进行比较
【发布时间】:2016-04-19 03:56:01
【问题描述】:

我正在尝试创建一个允许用户在文件中搜索名称的程序。该程序成功地做到了这一点,但后来我想到并不是每个人都会输入名称,因为它在文件中是大写的。也就是说,有人可能会搜索“sarah”,但由于该名称在文件中列为“Sarah”,因此将找不到该名称。为了解决这个问题,我尝试在比较时将两个字符串都转换为大写。我对自学 C 非常非常陌生,所以我不确定我是否朝着正确的方向前进。在这一点上,我什至无法编译程序,因为我收到两个错误,说“数组初始化程序必须是初始化程序列表或字符串文字”。我假设这意味着我的语法不仅无效,而且方向完全错误。实现我的目标的最佳方式是什么?

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

     int main(void)
     {
        FILE *inFile;
        inFile = fopen("workroster.txt", "r");
        char rank[4], gname[20], bname[20], name[20];

        printf("Enter a name: __");
        scanf("%s", name);
        int found = 0;
        while(fscanf(inFile, "%s %s %s", rank, bname, gname)== 3)
        {   char uppername[40] = toupper(name[15]);
            char upperbname[40] = toupper(bname[15]);
            if(strcmp(uppberbname,uppername) == 0)
            {
                printf("%s is number %s on the roster\n", name, rank);
                found = 1;
            }
        }

        if ( !found )
            printf("%s is not on the roster\n", name);

        return 0;

      }

【问题讨论】:

  • 一个很好的起点是了解您调用的 api 如何实际运行。例如,toupper 返回单个char,因此不适合初始化char array。顺便说一句,如果您不介意将马车挂在 posix 拖拉机上,strcasecmp 可能会使这项任务变得更容易(或在 Windoze 中使用_stricmp)。
  • 确保您验证并限制所有输入。例如if (scanf ("%19[^\n]%*c", name) != 1) { fprintf (stderr, "error: invalid input.\n"); return 1;} 不仅仅是您从文件中读取的输入。如果用户输入someverylongstring__%%with+malicious+commands%%怎么办?

标签: c arrays strcmp toupper


【解决方案1】:

这两行是错误的:

char uppername[40] = toupper(name[15]);
char upperbname[40] = toupper(bname[15]);

int toupper(int c); takes an int and returns an int

因为在 C 中字符串只是一个带有空终止符的字符数组,所以你可以做的就是将字符串的每个字符转换为大写:

for (size_t I = 0; I < strlen(name); I++) {
    uppername[I] = toupper(name[I]);
}
uppername[I] = '\0';

关于比较,您可以按照建议使用strcasecmp,即Posix。 如果只想使用 C 标准库中的函数,请按上述转换字符串,然后使用strcmp

【讨论】:

    【解决方案2】:

    toupper() 作用于单个字符,而不作用于字符串。

    无需转换输入字符串。简单地调用一个不区分大小写的字符串比较。

    由于 C 没有标准的,因此很容易创建自己的。

    int mystricmp(const char *s1, const char *s2) {
      // toupper works with unsigned char values.
      // It has trouble (UB) with char, when char is signed.
      const unsigned char *p1 = (const unsigned char *) s1;   
      const unsigned char *p2 = (const unsigned char *) s2;   
    
      while (toupper(*p1) == toupper(*p2) && *p1) {
        p1++;
        p2++;
      }
    
      int ch1 = toupper(*p1);
      int ch2 = toupper(*p1);
      return (ch1 > ch2) - (ch1 < ch2);
    }
    

    【讨论】:

      【解决方案3】:

      使用下面的函数,包含在strings.h

      int strcasecmp(const char *s1, const char *s2);
      

      在你的情况下改变 if 语句

      if(strcmp(uppberbname,uppername) == 0)
      

      if(strcasecmp(bname,name) == 0)
      

      然后删除

      char uppername[40] = toupper(name[15]);
      char upperbname[40] = toupper(bname[15]);
      

      【讨论】:

      • 注意:strcasecmp() 不在标准 C 库中。
      • @user3302647 strcasecmp()POSIX 而不是 C standard
      【解决方案4】:

      因为函数toupper 用于将字符从小到大转换,所以不能将它用于字符串大小写转换。但是您可以通过这种方式使用相同的函数进行字符串化:

        while(name[i])
        {
           uppername[i]=toupper(name[i]);
           i++;
        }
        while(bname[j])
        {
           upperbname[j]=toupper(bname[j]);
           j++;
        }
      

      这些语句进行我们的字符串大小写转换。整个节目:

      #include <stdio.h>
      #include <ctype.h>
      #include <string.h>
      int main(void) {
        FILE *inFile;
        inFile = fopen("workroster.txt", "r");
        char rank[4], gname[20], bname[20], name[20], uppername[40], upperbname[40];
        printf("Enter a name: __");
        scanf("%s", name);
        int found = 0, i = 0, j = 0;
      
        while (fscanf(inFile, "%s %s %s", rank, bname, gname) == 3) {
          while (name[i]) {
            uppername[i] = toupper(name[i]);
            i++;
          }
          while (bname[j]) {
            upperbname[j] = toupper(bname[j]);
            j++;
          }
      
          //char uppername[40] = toupper(name[15]);
          //char upperbname[40] = toupper(bname[15]);
          if (strcmp(uppername, upperbname) == 0) {
            printf("%s is number %s on the roster\n", name, rank);
            found = 1;
          }
        }
      
        if (!found) printf("%s is not on the roster\n", name);
        return 0;
      }
      

      【讨论】:

      • uppername[]upperbname[j] 缺少空字符。
      • 有了这个,它只是说我正在搜索的名字都没有找到。
      猜你喜欢
      • 2015-06-27
      • 2015-07-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多