c - 我在带有分隔符的文本文件中有一组值如何使用 C 编程修改值

标签 c arrays text-files

我拥有的文本文件包含以下数据(分别以 K 和 D 和 P 作为 ID 开始)

K1234:Green_Book:A_green_book:10:
K3346:Red_Book:A_red_book:7:
D3333:Grey_Book:A_grey_book:15:
D1111:Black_Book:A_black_book:1:
P0000:White_Book:A_white_book:6:

我想做的是修改以 D3333 开头的行中的数据并将值从 更改15 至 17 在文本文件中。我真的不知道该怎么做,因为我是 C 编程的新手,这已经困扰了我好几天了。我已经在整个网络上进行了搜索,但我的搜索无济于事。如果有人可以帮助我提供可以执行此操作的代码或类似的代码,我将不胜感激。谢谢。

这是我到目前为止所做的:

void show(){
    FILE * fl;
    long fl_size;
    char * buffer;
    size_t res;

    fl = fopen("inventItems.txt", "r+");
    if (fl == NULL) {
        fprintf(stderr, "File error\n");
        _getch();
        exit(1);
    }

    fseek(fl, 0, SEEK_END);
    fl_size = ftell(fl);
    rewind(fl);

    buffer = (char*)malloc(sizeof(char)*fl_size);
    if (buffer == NULL) {
        fputs("Memory error", stderr);
        _getch();
        exit(2);
    }

    res = fread(buffer, 1, fl_size, fl);
    if (res != fl_size) {
        fputs("Reading error", stderr);
        _getch();
        exit(3);
    }
    char * strtok_res;
    strtok_res = strtok(buffer, ":");
    while (strtok_res != NULL)
    {
        printf("%s\n", strtok_res);//this prints the values from the file to a new line when i test it
        //however i DO NOT KNOW how to modify and save it back onto the text file
        strtok_res = strtok(NULL, ":");
        _getch();
    }
    _getch();
    fclose(fl);
    free(buffer);

}

最佳答案

好的,看起来你这样做是正确的。一些评论:
重复性和可读性
你经常重复自己;变化

if(whateverPointer == NULL) {
   fprintf("My error message", stderr);
   _getch();
   exit(2);
}
在三个不同的场合使用;所以应该移动到一个单独的函数中,该函数需要一个 char* (字符串)要传递给 fprintf() 的消息,这样你就可以做到
if(whateverPointer == NULL) {
   errorThenDeath("My message", 2);
}
这似乎与问题无关,但除了是一个好习惯之外,它还会使您的代码更易于阅读。你的代码越容易阅读,当你遇到困难时,其他人就越容易帮助你:永远记住这一点。
在类似的情况下,您已表示要使用特定标识符来更改特定行。考虑到这一点,您应该将问题分解以识别此特定问题,因此执行该特定任务的代码应包含在可能具有此类签名的函数中。
int changeLineValue(char** buffer, size_t size, char* identifier, int newValue) 
{
...
}
注意双指针( char** )这是指向原始 char* 的指针.当在这个函数内部时,你可以通过取消引用来获得原始指针( * )所以
*buffer = "hello";
将缓冲区更改为字符串“hello”。
问题
我不确定标记缓冲区是正确的方法。 strtok实际上写入\0每个 token 末尾的字符,当您尝试将其写回文件时会很痛苦。还有一点要注意;因为您不知道新号码可能有多少位数,所以您可能需要调整缓冲区的大小以进行补偿。函数签名假定这已完成,并返回一个数字,表示添加或删除了多少字符(如果有)。
我的一般方法是遍历每个字符以寻找换行符。每次找到一个,检查它是否是正确的行,如果是,获取值,确定是否需要调整缓冲区大小并在必要时这样做。完成后,更改值。
int changeLineValue(char** buffer, size_t size, char* identifier, int newValue) 
    for(int i = 0; i < size; i++) {
        if(buffer[i] == '\n' && isCorrectLine(*buffer, size, i)) {
           int oldVal = getCurrentValue(*buffer, size, i);
           int resize = getDigitsDifference(oldVal, value);
           if(resize != 0) {
              resizeBuffer(buffer, resize);
           }
           modifyValueInPosition(buffer, fl_size, i, value);
           return resize;
        }
    }
}
笔记;由于 C 语言的工作方式,isCorrectLine(...)只有在 buffer[i] == \n 时才会调用评估为真。这称为 short circuit evaluation .
显然,上面的代码调用了几个尚未创建的函数,因此您的部分任务将是实现它们。请注意,第二个参数已通过 fl_size定义为 size_t不是 long即使 fl_size是长。您应该将此变量更改为 size_t .
下面我提供了函数签名。由于您正在尝试学习 C,因此我不会为您实现它们。
每次遇到换行符时都会调用此函数,并将“索引”设置为该换行符的位置。如果在这个位置没有找到标识符,它应该返回一个 0,如果在这个位置找到它,它应该返回一个 1。此时不要更改缓冲区中的任何内容
int isCorrectLine(char* buffer, char* identifier, size_t size, int index) {
}
此函数应沿行迭代并返回下一个换行符('\n')之前的数字
int getCurrentValue(char* buffer, size_t fl_size, i) {
}
这个数字应该返回每个数字有多少位数之间的差异。例如。 1 = 1 位,324 = 3 位,所以 3 - 1 = 2
int digitsDifference(int old, int new) {
}
此函数采用双指针 (char**) 并使用更大或更小的缓冲区重新分配内存,以便在需要时考虑不同的位数。
void resizeBuffer(char** buffer, int resize) {
    *buffer = // This is how you change the original pointer. Line is still incomplete 
}
现在缓冲区的大小是正确的,您可以继续更改缓冲区中的值。同样,此函数在正确行之前的换行符位置传递,因此您需要沿行迭代,更改位置值。如果您发现自己覆盖了换行符(因为新数字较长),您可能需要将此值之后的所有字符移动
int modifyValueInPosition(char* buffer, size_t fl_size, int index) {
}
写入文件
更改原始缓冲区后,将其写回文件相当容易。您的主要功能现在应该看起来像这样
int main() {
    // ...code that gets buffer from file. Note, make sure you close the file handle
    // afterwards it isn't good practise to leave a file handle open
    
    fl_size += changeLineValue(buffer, fl_size, identifier, newValue);
    
    // ...Reopen file handle as you did before ...

    fwrite(buffer, sizeof(char), fl_size, fileHandle);

    // ...Close file handle...
}

关于c - 我在带有分隔符的文本文件中有一组值如何使用 C 编程修改值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39815855/

相关文章:

c - C 宏在不同情况下的不同行为

c - 以下 for 循环语法在 C 中是什么意思?

c++ - 如何读取自定义 TIFF 标签(无 TIFFFieldInfo)

python - 制作类似于 MATLAB 的 Python 2D 掩码数组

c# - 如果文件已经存在,如何覆盖?

c# - 当我将项目保存在列表框中时,它们之间的行太多

c - int main() { }(没有 "void")在 ISO C 中有效且可移植吗?

ios - ISO8601 格式在 MongoDB 和 iOS 中不同

c# - 在文本文件中搜索特定单词并显示其所在的行

javascript - 从表 JS 中的输入获取元素 id