You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C语言用strtok分割文件逐行内容报invalid initializer错误如何解决

现存问题拆解

你这段代码一共有几类错误,编译报错是最表层的,还有隐藏的文件操作、字符串处理逻辑错误:

  • 编译错误根因:C语言不允许在定义字符数组时,直接用strtok()返回的char*指针作为数组初始化值。字符数组的初始化仅接受字符串字面量、字符初始化列表,直接把指针赋值给数组初始化器就会触发invalid initializer报错。
  • 冗余+危险的文件操作:刚调用fopen打开文件时,文件指针本来就指向文件起始位置,完全没必要调用rewind(fp);而且你没有判断fopen的返回值,如果文件不存在、权限不足导致打开失败,fp是空指针,后续所有对fp的操作都会触发未定义行为直接崩溃。
  • 字符串读取逻辑错误:fread是按字节块读取的函数,不会自动在读取到的内容末尾添加C字符串要求的\0结束符,后续把buffer当字符串处理时会越界读取内存垃圾值;而且你固定只读取1块100字节的内容,文件长度超过100字节的内容会丢失,文件不足100字节时也不会做截断处理。
  • strtok使用逻辑错误:你只调用了一次strtok(buffer, "\n"),最多只能拿到第一行的片段,要切出所有行必须循环调用strtok(NULL, "\n")直到返回值为NULL;而且strtok返回的是指向buffer内部位置的指针,如果直接存这个指针,后续切分下一行时会修改buffer里的内容,之前存的指针指向的内容会被篡改。
可直接运行的修正代码

优先推荐逐行读取方案,不需要手动做内存切分,出bug概率更低:

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

#define MAX_LINE_CNT 100  // 最多存储100行条目
#define MAX_LINE_LEN 100  // 单条内容最长支持100字符

int main() {
    FILE* fp = fopen("storeroom.csv", "r");
    if (fp == NULL) {
        perror("文件打开失败");
        return 1;
    }

    // 二维数组,每个子数组存一行独立的站点密码条目
    char lines[MAX_LINE_CNT][MAX_LINE_LEN];
    int line_cnt = 0;

    // 逐行读取,直到文件结束或者数组存满
    while (line_cnt < MAX_LINE_CNT && fgets(lines[line_cnt], MAX_LINE_LEN, fp) != NULL) {
        // 清除fgets自带读入的末尾换行符
        char* newline_pos = strchr(lines[line_cnt], '\n');
        if (newline_pos != NULL) {
            *newline_pos = '\0';
        }
        line_cnt++;
    }

    fclose(fp);

    // 测试输出所有读入的条目
    for (int i = 0; i < line_cnt; i++) {
        printf("第%d条内容:%s\n", i+1, lines[i]);
    }

    return 0;
}

如果你一定要用strtok切分整块读入内容的方案,参考下面的实现:

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

#define BUF_SIZE 1024  // 缓冲区大小要足够装下整个文件内容
#define MAX_LINE_CNT 100
#define MAX_LINE_LEN 100

int main() {
    FILE* fp = fopen("storeroom.csv", "r");
    if (fp == NULL) {
        perror("文件打开失败");
        return 1;
    }

    char buffer[BUF_SIZE] = {0}; // 初始化全0,自动补字符串结束符
    fread(buffer, 1, BUF_SIZE-1, fp); // 预留1字节放结束符
    fclose(fp);

    char lines[MAX_LINE_CNT][MAX_LINE_LEN];
    int line_cnt = 0;

    // 第一次调用strtok切分第一行
    char* token = strtok(buffer, "\n");
    while (token != NULL && line_cnt < MAX_LINE_CNT) {
        // 把切出来的内容拷贝到数组,不要直接存strtok返回的内部指针
        strncpy(lines[line_cnt], token, MAX_LINE_LEN-1);
        lines[line_cnt][MAX_LINE_LEN-1] = '\0'; // 手动补结束符防止字符串溢出
        line_cnt++;
        // 后续切分传入NULL,拿到下一行的起始位置
        token = strtok(NULL, "\n");
    }

    // 测试输出
    for (int i = 0; i < line_cnt; i++) {
        printf("第%d条内容:%s\n", i+1, lines[i]);
    }

    return 0;
}
关键注意点
  • 所有文件操作必须先判断打开是否成功,禁止直接操作空指针
  • C语言里数组不能直接被赋值,也不能用返回的指针直接初始化字符数组,要存储指针指向的字符串内容,必须用strcpy/strncpy做内存内容拷贝
  • 处理C字符串时一定要保证末尾有\0结束符,否则会出现内存越界读垃圾值、程序崩溃的问题
  • strtok会直接修改原输入缓冲区的内容,使用时不要依赖原缓冲区保存的原始内容

内容的提问来源于stack exchange,提问作者user18025483

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 06:12:16