【问题标题】:Token Ignore some elements in the StringToken 忽略String中的一些元素
【发布时间】:2024-01-09 00:00:01
【问题描述】:

我正在尝试实施一个项目来读取十六进制数字并对其进行排序。当我在代码中硬写输入时,代码与我一起正确工作,但是当我修改代码以从文本文件中获取输入时,我得到了不正确的结果,当我调试代码时,我发现令牌没有得到所有的值,我不知道为什么。

这是我的代码:

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

int main()
{


    FILE *in_file  = fopen("input.txt", "r");
    FILE *out_file = fopen("output.txt", "w");


    int bufferLength = 255;
    char buffer[bufferLength];

      if (in_file == NULL)
    {
      printf("Error! Could not open file\n");
      exit(-1);
    }

    char input[] = {};

    fgets(input, bufferLength, in_file);


    int decimal[1000] = {0};

    char * token = strtok(input, " ");
    int n = (int) strtol(token, NULL, 16);
    decimal[0] = n;

    printf("N is : %d , token is : %s \n", n, token);

    int no = 0;
    while(token != NULL) {
      token = strtok(NULL, " ");
      int n = (int) strtol(token, NULL, 16);
      decimal[no+1] = n;
      no++;
      printf("N is : %d , token is : %s \n", n, token);
   }


int temp = 0;

    //Sort the array
    for (int i = 0; i < no; i++) {
        if (decimal[i] == 0){
            break;
        }
        for (int j = i+1; j < no; j++) {
           if(decimal[i] > decimal[j]) {
               temp = decimal[i];
               decimal[i] = decimal[j];
               decimal[j] = temp;
           }
        }
    }



    //Print elements
    for (int j = 0; j < no; j++){
        fprintf(out_file,"%X ", decimal[j]);
    }


    fclose(in_file);
    fclose(out_file);

    return 0;
}

输入是:10 A B 1,但是在调试代码时我得到了以下结果:

N is : 16 , token is : 10
N is : 10 , token is : A

N is : 0 , token is : (null)

【问题讨论】:

  • edit 并显示格式正确的最小版本的 input.txt 文件。以及预期与实际输出。
  • char input[] = {}; input 数组的固定长度为零,这没有意义。你想要char input[bufferLength] = {0};。不过可能还有其他问题。
  • printf("Error! Could not open file\n"); 是无用错误消息的典型示例。试试perror("input.txt");

标签: c token


【解决方案1】:

你的代码基本上有两个问题:

  1. char input[] = {}; 声明一个大小为零的数组。当您使用 fgets(input, ....) 时,您将写入超出此数组的末尾,这将导致未定义的行为。
  2. token = strtok(NULL, " ") 之后,一旦没有更多标记,token 将变为 NULL,然后您在此处取消引用此 NULL 指针:strtol(token, NULL, 16);

所以你需要改变:

char input[] = {};

char input[bufferLength] = {0};

你需要检查strtok是否返回NULL:

  while (1) {   //<< change this (loop forever)
    token = strtok(NULL, " ");

    if (token == NULL)  // << add this
      break;            // << add this

    int n = (int)strtol(token, NULL, 16);
    decimal[no + 1] = n;
    no++;
    printf("N is : %d , token is : %s \n", n, token);
  }

免责声明:排序部分可能有问题,我没有检查。

奖励:

你可以替换这个:

 while (1) {   //<< change this (loop forever)
    token = strtok(NULL, " ");

    if (token == NULL)  // << add this
      break;            // << add this

使用这个稍微短一些的代码:

 while ((token = strtok(NULL, " ") != NULL)   
 {

但我不确定这是否适合初学者...

【讨论】:

  • 将数组的声明更改为您所说的会引发错误“可变大小对象可能未初始化”
  • @MostafaKhaled 不需要初始化。写char input[bufferLength];
  • ... 或者,只使用buffer,这似乎是用于输入的。
最近更新 更多