C-为什么char数组只返回放入其中的最后一个值?

时间:2019-04-18 17:38:51

标签: c

我正在用C语言编写。我试图从文本文件中读取行,分析行,然后将一些信息放入字符串数组中。当我测试代码时,数组中的每个值似乎都是最后插入的值。是什么原因造成的?

int r;
char *users[51]; //given no more than 50 users
for (r = 0; r < 51; r++) {
    int n = 15; //arbitrary guess at length of unknown usernames
    users[r] = malloc((n + 1) * sizeof(char));
}
FILE *fp;
fp = fopen(argv[1], "r");

char *username;

int counter = 0;
char line[100];
while (fgets(line, 100, fp) != NULL) {
    username = strtok(line, ":");

    users[counter] = username;
    printf("%s\n", username);
    printf("%s\n", users[counter]);

    //counter increase for later
    counter += 1;

4 个答案:

答案 0 :(得分:1)

您在数组中的每个条目中都添加了一个有意义的值:

users[r] = malloc((n+1) * sizeof(char));

但是您随后用一个无意义的值(指向line的指针)覆盖了它:

users[counter] = username;

您大概想做的就是将username指向的字符串复制到users[counter]分配的空间中。 strcpy函数可以做到这一点。

答案 1 :(得分:1)

strtok是一个非常令人困惑的功能:

  • 它修改接收指针的数组
  • 它返回一个指向该数组元素的指针。
  • 它保持内部状态,使其不可重入且不具有线程安全性。

因此username内的line点。您将此指针存储到users[counter]中。在循环结束时,users中的所有条目都指向每次调用fgets()都已覆盖的同一数组。

您应该使用strdup()复制数组的内容:

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

int main(int argc, char *argv[) {
    char *users[51]; //given no more than 50 users
    int r;
    FILE *fp;

    if (argc < 2) {
        fprintf(stderr, "missing filename argument\n");
        return 1;
    }
    fp = fopen(argv[1], "r");
    if (fp == NULL) {
        fprintf(stderr, "cannot open file %s\n", argv[1]);
        return 1;
    }
    char line[100];
    int counter = 0;
    while (counter < 50 && fgets(line, 100, fp) != NULL) {
        char *username = strtok(line, ":");
        if (username != NULL) {
            users[counter] = strdup(username);
            //counter increase for later
            counter += 1;
        }
    }
    users[counter] = NULL;

    ...
}

答案 2 :(得分:-1)

我想补充一下David的答案,即在使用strcpy()之前,还应检查用户名字符串是否为空终止。我不记得strtok() null是否终止,但您仍然不应该依赖它。

答案 3 :(得分:-1)

避免指针数组的解决方案:

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

#define NAMELEN  16
#define MAXUSERS 51
typedef char uarray[MAXUSERS][NAMELEN];

int main() {
    int i;
    uarray * users = malloc(sizeof(uarray));
    memset(users, 0, MAXUSERS*NAMELEN);
    strncpy((*users)[0], "Alice", NAMELEN-1);
    strncpy((*users)[1], "Bob", NAMELEN-1);

    for (i=0; i<2; i++) 
        printf("%d: %s\n", i, (*users)[i]);
    return 0;
}