gpt4 book ai didi

c - 如何在C中编辑文本文件的特定行

转载 作者:太空宇宙 更新时间:2023-11-04 08:18:20 25 4
gpt4 key购买 nike

我目前正试图在C中编辑.txt文件的特定行。im使用的文件如下所示:
Pixel location and RGB Color
现在假设我想更改在图像上突出显示的特定行上写的内容:
400300:(255255255)飞夫
进入这个:
400300:(000000000)亿
基本上,我试图在特定的像素上创建一个黑点,在本例中是400300。这就是我的代码:

#include <stdio.h>
int main(void)
{
const char *filename = "sample.txt";
int x = 400;
int y = 300;

FILE *fp;
fp = fopen(filename, "w+");

// Algorithm that reads all the file

// If("Operation that reads" == x+","+y)
// {
// Replace the line information after where it starts with "400,300"
// Like this : 400,300: (000,000,000) #000000
// }


// Algorithm that saves the file with the changes.


fclose(fp)
printf("Ok - File %s saved\n", filename);
return 0;

创建、打开和编辑.txt文件对我来说有点新鲜,所以我不知道该怎么做,我读的越多,就越困惑。我该如何解决这个问题?这里适合哪些代码?
更新1:
FILE *fp;
fp = fopen(filename, "w+");

if ( fp == NULL )
{
printf("Error while opening file");
}

好吧,看了你放在下面的东西后,我想出了一个主意,但仍然需要工作。我会打印从文件到字符数组的所有内容。在那之后,我会在每个插槽中搜索我正在寻找的特定代码行,并保留数字插槽。之后,我会转到array,运行它,当它到达那个特定的插槽时,我会替换所需的数据。现在我需要做的就是把文件中的信息换成数组中的信息,保存文件并解决问题。但是im在代码中出现错误,im丢失了清除txt文件并保存新数据的代码位。
更新2:
#include <stdio.h>

int main(void)
{

int x,y;
int k = 0;
int noline; // Used to locate which line is the string im looking for
char search; // Used to compare with each string
char blackcode = (char)000; // In RGB, Black uses (000,000,000)
char blackhexcode = (char)000000; // The hexcode for black is #000000
const char *filename = "sample.txt";
char* strings[480000]; // Since its a 800x600 resolution picture, it needs that many lines.
char line[30]; // Space created to store whats inside each line of the file before transfering
char temp;

FILE * fp;
fp= fopen(filename, "r+");

if ( fp == NULL )
{
printf("Error while opening file");
}
else
{
while(fgets(line, sizeof line, fp))
{
strings[k]=strdup(line); // ERROR HERE! What Am I missing?
k++;
}

for(k = 0; k< sizeof strings; k++)
{
temp = scanf("%[^:]s", strings[k]);
search = ("%s,%s",x,y);

if(temp = search)
{
noline = k;
}
else
{
printf("Error : Wrong Coordinates");
}
}

for(k = 0; k < sizeof strings; k++)
{
if(k == noline)
{
strings[k] = ("%d,%d: (%s,%s,%s) #%s", x, y, blackcode, blackcode, blackcode, blackhexcode); // ERROR HERE! What did i did wrong?
}
}

// Code that cleans the txt file and saves the array back to txt file
}
fclose(fp);

}

最佳答案

您缺少的是一些概念性的,并且与fopen有关。当您考虑使用fopen打开文件时,需要特别注意文件模式的效果。如果您仔细查看有关"w""w+"的手册页。在这两种情况下,现有文件都被截断。在0-length的情况下"w"
为了避免这个问题,一种方法是将整个文件读入缓冲区,然后对缓冲区进行更改,将修改后的缓冲区写回原始文件名。这避免了在不重写文件其余部分的情况下尝试插入/删除字节的可能性。
要处理将文件读入缓冲区的操作,postoverwriting a specific line on a text file?链接提供了更改文件中单行的路线图。你的情况不同。要查找/替换某个特定图案的所有引用。(这就是截断问题带来挑战的地方)不管有多少解决方案可以应用于将文件本身读入缓冲区。特别是fseekftell的使用。
使用fseekftell提供了一种简单的方法来确定文件的大小(或长度),然后可用于分配空间以将整个文件保存在内存中。下面是一个简单函数的方法,该函数接受字符指针和文件指针的地址,然后使用fseekftell分配所需的内存来保存文件,然后使用filebuf在单个操作中将文件读入缓冲区(fread)。缓冲区已填充、就位并返回。将指向文件长度fplen的指针传递给函数,以便在调用函数中返回该长度(在本例中为main())。如果需要,在成功时返回指向缓冲区的指针(NULL否则)将允许分配返回,以及确定读取成功/失败的方法:

char *read_file_into_buf (char **filebuf, long *fplen, FILE *fp)
{
fseek (fp, 0, SEEK_END);
if ((*fplen = ftell (fp)) == -1) { /* get file length */
fprintf (stderr, "error: unable to determine file length.\n");
return NULL;
}
fseek (fp, 0, SEEK_SET); /* allocate memory for file */
if (!(*filebuf = calloc (*fplen, sizeof *filebuf))) {
fprintf (stderr, "error: virtual memory exhausted.\n");
return NULL;
}

/* read entire file into filebuf */
if (!fread (*filebuf, sizeof *filebuf, *fplen, fp)) {
fprintf (stderr, "error: file read failed.\n");
return NULL;
}

return *filebuf;
}

一旦你把文件放在内存中,谜题的第二个部分就是简单地扫描缓冲区并进行所需的替换。这里有许多不同的调整可以应用于优化搜索/替换,但以下只是一个简单的基本搜索/替换,其中唯一的优化尝试是在使用normal string.h字符串比较函数检查指定的搜索字符串之前比较起始字符。函数返回替换的次数,以便您可以确定是否需要对原始文件名进行写操作:
unsigned find_replace_text (char *find, char *rep, char *buf, long sz)
{
long i;
unsigned rpc = 0;
size_t j, flen, rlen;

flen = strlen (find);
rlen = strlen (rep);

for (i = 0; i < sz; i++) {
/* if char doesn't match first in find, continue */
if (buf[i] != *find) continue;

/* if find found, replace with rep */
if (strncmp (&buf[i], find, flen) == 0) {
for (j = 0; buf[i + j] && j < rlen; j++)
buf[i + j] = rep[j];
if (buf[i + j])
rpc++;
}
}

return rpc;
}

使用示例数据将所有部分放在一个简短的示例程序中可以编写如下。程序要求将文件名作为第一个参数(如果未给定文件名,则默认情况下,它将从 stdin读取并写入 stdout)。您还可以包括其他验证检查:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>

char *read_file_into_buf (char **filebuf, long *fplen, FILE *fp);
unsigned find_replace_text (char *find, char *rep, char *buf, long sz);

int main (int argc, char **argv) {

char *srchstr = "400,300";
char *repstr = "400,300: (000,000,000) #000000";
char *filebuf = NULL;
long int fplen = 0;
FILE *fp = NULL;

/* open file for reading (default stdin) */
fp = argc > 1 ? fopen (argv[1], "r") : stdin;

if (!fp) { /* validate file open */
fprintf (stderr, "error: file open failed '%s'\n", argv[1]);
return 1;
}

if (!read_file_into_buf (&filebuf, &fplen, fp)) return 1;
if (fplen < 1 || fplen >= INT_MAX) { /* validate file length */
fprintf (stderr, "error: length of file invalid for fwrite use.\n");
return 1;
}
if (fp != stdin) fclose (fp);

/* find/replace text in filebuf */
if (!find_replace_text (srchstr, repstr, filebuf, fplen)) {
printf ("no replacements made.\n");
return 0;
}

/* open file for writing (default stdout) */
fp = argc > 1 ? fopen (argv[1], "w") : stdout;

if (!fp) { /* validate file open */
fprintf (stderr, "error: file open failed '%s'\n", argv[1]);
return 1;
}

/* write modified filebuf back to filename */
if (fwrite (filebuf, sizeof *filebuf, (size_t)fplen, fp) != (size_t)fplen) {
fprintf (stderr, "error: file write failed.\n");
return 1;
}
if (fp != stdout)
if (fclose (fp) == EOF) {
fprintf (stderr, "error: fclose() returned EOF\n");
return 1;
}

free (filebuf);

return 0;
}

只包括文件底部的函数。你可以:
编译
gcc -Wall -Wextra -O3 -o bin/fread_file fread_file.c

(或者在编译器中使用等效的编译字符串)
输入文件
$ cat dat/rbgtst.txt
400,280: (234,163,097) #EAA361
400,300: (255,255,255) #FFFFFF
400,320: (064,101,160) #4065A0
400,340: (220,194,110) #DCC26E

更换后使用/归档
$ ./bin/fread_file dat/rbgtst.txt
$ cat dat/rbgtst.txt
400,280: (234,163,097) #EAA361
400,300: (000,000,000) #000000
400,320: (064,101,160) #4065A0
400,340: (220,194,110) #DCC26E

或从 stdin写入到 stdout
$ ./bin/fread_file <dat/rbgtst.txt
400,280: (234,163,097) #EAA361
400,300: (000,000,000) #000000
400,320: (064,101,160) #4065A0
400,340: (220,194,110) #DCC26E

内存/错误检查
在动态分配内存的任何代码中,对于分配的任何内存块,您都有两个职责:(1)始终保留指向内存块起始地址的指针,以便(2)在不再需要时可以释放它。
必须使用内存错误检查程序,以确保没有在已分配的内存块之外写入数据,尝试读取未分区的值或在未分区的值上进行跳转,最后确认已释放已分配的所有内存。
对于Linux valgrind是正常的选择。有很多微妙的方法可以滥用新的内存块。使用内存错误检查器可以识别任何问题,并验证您分配的内存的正确使用,而不是通过 segfault发现问题。每个平台都有类似的内存检查程序。它们都很容易使用,只要运行你的程序就可以了。例如。:
$ valgrind ./bin/fread_file dat/rbgtst.txt
==13768== Memcheck, a memory error detector
==13768== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al.
==13768== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info
==13768== Command: ./bin/fread_file dat/rbgtst.txt
==13768==
==13768==
==13768== HEAP SUMMARY:
==13768== in use at exit: 0 bytes in 0 blocks
==13768== total heap usage: 3 allocs, 3 frees, 2,128 bytes allocated
==13768==
==13768== All heap blocks were freed -- no leaks are possible
==13768==
==13768== For counts of detected and suppressed errors, rerun with: -v
==13768== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 2 from 2)

您要确认 All heap blocks were freed -- no leaks are possibleERROR SUMMARY: 0 errors from 0 contexts(忽略与未安装在我的系统上的缺少调试符号文件有关的禁止注释)
检查代码并理解它在做什么。这不是作为唯一的方式来做你正在尝试做的事情,但是它被呈现为如何解决这个问题的例子,同时避免了试图利用偏移和对文件的多次读/写改变现有文件中的一行一次的固有缺陷。如果你有问题请告诉我。

关于c - 如何在C中编辑文本文件的特定行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34536508/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com