首页 > 解决方案 > 如何将字符串值转换为数值?

问题描述

我试过这段代码将我的 Str[] 字符串分成 2 个字符串,但我的问题是“我想将 John(name) 分隔为字符串,将 100(marks) 分隔为整数”,我该怎么做,有什么建议吗?

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

    void main()
    {
        char Str[] = "John,100";
        int i, j, xchange;
        char name[50];
        char marks[10];
        j = 0; xchange = 0;

        for(i=0; Str[i]!='\0'; i++){
            if(Str[i]!=',' && xchange!=-1){
                name[i] = Str[i];
            }else{
                xchange = -1;
            }
            if(xchange==-1){
                marks[j++] = Str[i+1];
            }
        }
        printf("Student name is %s\n", name);
        printf("Student marks is %s", marks);
    }

标签: cstring

解决方案


如何将“John,100”分成 2 个字符串?

常见的方法有以下三种:

  1. 用于strtok()将字符串拆分为单独的标记。这将修改原始字符串,但实现起来非常简单:

    int main(void)
    {
        char  line[] = "John,100;passed";
        char *name, *score, *status;
    
        /* Detach the initial part of the line,
           up to the first comma, and set name
           to point to that part. */
        name = strtok(line, ",");
    
        /* Detach the next part of the line,
           up to the next comma or semicolon,
           setting score to point to that part. */
        score = strtok(NULL, ",;");
    
        /* Detach the final part of the line,
           setting status to point to it. */
        status = strtok(NULL, "");
    

    请注意,如果您更改char line[] = "John,100";then statuswill be NULL,但代码可以安全运行。

    因此,在实践中,如果您要求所有三个字段都存在于 中line,则确保最后一个字段不存在就足够了NULL

        if (!status) {
            fprintf(stderr, "line[] did not have three fields!\n");
            return EXIT_FAILURE;
        }
    
  2. 用于sscanf()转换字符串。例如,

        char  line[] = "John,100";
        char  name[20];
        int   score;
    
        if (sscanf(line, "%19[^,],%d", name, &score) != 2) {
            fprintf(stderr, "Cannot parse line[] correctly.\n");
            return EXIT_FAILURE;
        }
    

    这里,19指的是字符的数量name(一个总是为字符串结尾的 nul char 保留'\0'),并且[^,]是字符串转换,消耗除逗号之外的所有内容。%d转换一个int. 返回值是成功转换的次数。

    这种方法不会修改原始字符串,它允许您尝试多种不同的解析模式;只要您首先尝试最复杂的一种,您就可以允许多种输入格式,而添加的代码很少。在将 2D 或 3D 矢量作为输入时,我经常这样做。

    缺点是sscanf()(scanf 系列中的所有函数)忽略溢出。例如,在 32 位架构上,最大int的是2147483647,但 scanf 函数会很高兴地将 eg 转换99999999991410065407(或其他值!)而不会返回错误。您只能假设数字输入是正常的并且在限制范围内;你无法验证。

  3. 使用辅助函数来标记和/或解析字符串。

    通常,辅助函数类似于

    char *parse_string(char *source, char **to);
    char *parse_long(char *source, long *to);
    

    wheresource是指向要解析的字符串中下一个字符的指针,并且to是指向将存储解析值的位置的指针;或者

    char *next_string(char **source);
    long  next_long(char **source);
    

    其中source是指向要解析的字符串中下一个字符的指针,返回值是提取的标记的值。

    这些往往比上面更长,如果是我写的,那么对他们接受的输入非常偏执。(如果他们的输入不能被可靠地解析,我希望我的程序抱怨,而不是默默地产生垃圾。)


如果数据是从文件中读取的CSV(逗号分隔值)的某种变体,那么正确的方法是不同的:不是逐行读取文件,而是逐个读取文件标记。

唯一的“技巧”是记住结束标记的分隔符(您可以使用ungetc()它),并使用不同的函数来(读取并忽略当前记录中的其余标记,并)使用换行符分隔符。


推荐阅读