【问题标题】:Random changing of values of array of structs结构数组值的随机变化
【发布时间】:2017-02-18 00:51:27
【问题描述】:

在我的代码中,我正在读取文件的名称和电话号码以及与电话号码对应的名称。我在代码中遇到的问题是在我的加载函数中的 for 循环之后。

这个问题是将我的结构名称的所有值随机更改为最后分配的名称。我也不完全理解如何从拆分令牌转换为从字符串浮动。

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


struct _data {
     char *name;
     long number;
};

int SCAN(FILE *(*stream)){
     int count;
     char dataString[50];
     int check = 1;
     count = 0;

     while(check){
          fscanf(*stream, "%s\n", dataString);
          fscanf(*stream, "%s\n", dataString);
          if (feof(*stream)){
               check = 0;
          }
          count++;
     }      
     return count;
}

struct _data *LOAD(FILE *stream, int size){
     int x;
     char *tempLine;
     size_t length = 0;
     const char delim[2] = " ";
     char *token;

     rewind(stream);
     struct _data *array = malloc(sizeof(struct _data) * size);  
     printf("this is the size: %d\n\n", size);
     for(x = 0; x < size; x++){
          getline(&tempLine, &length, stream);
          token = strtok(tempLine, delim);
          //printf("this is inside the for loop of load: %s\n", token);
          array[x].name = token;
          token = strtok(tempLine, delim);
          //printf("this is the token: %s\n", token);
          array[x].number = atol(token);
          printf("this is name %s, and phone number %ld\n", array[x].name, array[x].number);
     }
     printf("i am now outside the initial for loop in load\n\n");
     for(x = 0; x < size; x++){
               printf("this is name %s, and phone number %ld\n", array[x].name, array[x].number);
          }
     return array;

}

void SEARCH(struct _data *BlackBox, char *name, int size){
     int x;
     int check = 0;
     for(x = 0; x < size; x++){
          printf("BlackBox Name: %s, check name: %s\n", BlackBox[x].name, name);
          //printf("this is the check: %d\n", strcmp(BlackBox[x].name, name));
          if (0 == strcmp(BlackBox[x].name, name)){
               printf("*******************************************\n");
               printf("The name was found at the %d entry.\n", x);
               printf("*******************************************\n");
               check = 1;  
          }
     }
     if (check == 0){
          printf("*******************************************\n");
          printf("The name was NOT found.\n");
          printf("*******************************************\n");
     }
}

void FREE(struct _data *BlackBox, int size){
     free(BlackBox);
}

int  main(int argv, char **argc){
     FILE *fp;
     int size;
     int x;
     struct _data *BlackBox;
     if(argv < 2){
          printf("*******************************************\n");
          printf("* You must include a name to search for.  *\n");
          printf("*******************************************\n");
     }else{
          fp = fopen("hw5.data", "r");
          size = SCAN(&fp);
          BlackBox = LOAD(fp, size);
         /* for(x = 0; x < size; x++){
               printf("BlackBox Name: %s, check name: %s\n", BlackBox[x].name, argc[1]);
          }*/          
          SEARCH(BlackBox, argc[1], size);
          FREE(BlackBox, size);
     }
     return 0;
}

这是我的意见

ron 7774013
jon 7774014
tom 7774015
won 7774016
bonny 7774017

这是我的输出

ron 0
jon 0 
tom 0 
won 0 
bonny 0
i am now outside the initial for loop in load
bonny 0
bonny 0
bonny 0
bonny 0
bonny 0

【问题讨论】:

  • array[x].name = token; 只复制tempLine 中某个地方的指针,可能你想要一个字符串的副本。

标签: c struct dynamic-memory-allocation


【解决方案1】:

你不断重复使用getline() 分配的空间——所以你只能看到最后的值。您需要在循环后将 tempLine 设置为 NULL 并将 length 设置为 0。您还应该检查来自getline() 的返回值,以确保您确实获得了要读取的数据。

您对strtok() 的第二次调用应使用NULL 指针。通过重新指定tempLine,您将名称转换为数字。

      getline(&tempLine, &length, stream);
      token = strtok(tempLine, delim);
      //printf("this is inside the for loop of load: %s\n", token);
      array[x].name = token;
      token = strtok(tempLine, delim);
                     ^^^ should be NULL!

您在打印令牌时应该已经发现了这个问题。

此代码可能会按需要运行,但尚未编译。

struct _data *LOAD(FILE *stream, int size)
{
    char *tempLine = NULL;
    size_t length = 0;
    const char delim[] = " ";
    char *token;
    int x;

    rewind(stream);
    struct _data *array = malloc(sizeof(struct _data) * size);
    printf("this is the size: %d\n\n", size);
    for (x = 0; x < size; x++)
    {
        if (getline(&tempLine, &length, stream) == -1)
        {
            free(tempLine);
            break;
        }
        token = strtok(tempLine, delim);
        // printf("this is inside the for loop of load: [%s]\n", token);
        array[x].name = token;
        token = strtok(NULL, delim);
        // printf("this is the token: [%s]\n", token);
        array[x].number = atol(token);
        printf("%d: this is name %s, and phone number %ld\n", x, array[x].name, array[x].number);
        length = 0;
        tempLine = NULL;
    }
    printf("i am now outside the initial for loop in load\n\n");
    for (int i = 0; i < x; i++)
    {
        printf("%d: this is name %s, and phone number %ld\n", i, array[i].name, array[i].number);
    }
    return array;
}

另外请注意,您通常应该避免创建以下划线开头的名称(例如struct _data)。许多这样的名称保留给实现使用;最简单的方法是避免创建完全以下划线开头的名称。

【讨论】:

  • 是的!!!成功了,谢谢!!但是,是的,这是我使用教授的预定义函数,所以这就是为什么我有这样的名字(这就是他在家庭作业中定义它们的方式)
  • 你不能帮助有不良编码习惯的教授。记下这个问题,如果你有勇气就问它,并记住你自己的工作。
  • 所以,问题是因为我将每个索引上的名称设置为指针。因此,它被重定向到指针的地址,而指针的地址又具有最后一个值,我在这个假设中是否正确?
  • 是的——这基本上是正确的。如果你的行很长,你可能设法让getline() 分配一个更长的缓冲区,在这种情况下,你的数组中可能有两组值,但初始分配的阈值通常是 256,所以这条线确实会很长。通过在每次迭代中将长度和指针重置为 NULL,您可以强制 getline() 在每次调用时进行分配。分配是在检测到EOF之前完成的,所以EOF检测需要释放分配的空间。
  • 很好,谢谢。你真的帮助我学习,绝对是我见过的答案更好的人之一。
猜你喜欢
  • 2019-12-26
  • 1970-01-01
  • 2013-06-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-28
  • 2012-08-12
相关资源
最近更新 更多