我正在尝试编写将读取文本文件并将其存储到结构中的代码,以便可以将该结构用于程序。
struct Synonym{
char Ausdruck[100];
char Anmerkung[60];
};
typedef struct Synonym Synonym;
这是我的结构,我正在尝试拟合一个看起来像这样的文件
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Kernfission;Fission;Kernspaltung;Atomspaltung;
Wiederaufnahme;Fortfuehrung;
wegfahren;wegfliegen;abfliegen;aufbrechen;abfahren;abduesen (ugs.);davonfahren;fortfahren;abreisen;
Training;Kurs;Workshop;Weiterbildung;Seminar;Kursus;Bildungsmassnahme;Lehrgang;
Zerlegung;Demontage;Entlassung;Abbau;
#
之后的行应删除。 Ausdruck
中的每个单词及其后的()中都有一个单词,应保存在Anmerkung
中。问题是我需要像每行一样也是结构原因,因为在整个程序中,我需要能够从其中选择一行和两个单词来进行子手游戏。
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
struct Eintrag{
char Ausdruck[100][20];
char Anmerkung[100][20];
};
typedef struct Eintrag Eintrag;
int zeilencount(){
int count_lines = 0;
char chr;
FILE *datei = fopen("wort.txt","r");
if (datei == NULL) {
printf( "Fehlgeschlagen\n");
}
chr = getc(datei);
while (chr != EOF)
{
//Count whenever new line is encountered
if (chr == '\n')
{
count_lines = count_lines + 1;
}
if (chr == '#'){
count_lines = count_lines - 1;
}
//take next character from file.
chr = getc(datei);
}
fclose(datei);
count_lines ++;
return count_lines;
}
int main(){
int i,w,z,k;// loopindex
//fopen
int anzahlzeile = zeilencount();
Eintrag eintrag[anzahlzeile];
FILE *datei = fopen("wort.txt","r");
if (datei == NULL) {
printf( "Fehlgeschlagen\n");
}
for(i=0; i<anzahlzeile; i++){
for(w=0; w<10; w++){
for(z=0; z<20;z++){
fscanf(datei,"%c", &eintrag[i].Ausdruck[w][z]);
if(eintrag[i].Ausdruck[w][z]=='#'){
fscanf(datei, "%*[^\n]");
i=0;
break;
}
if(eintrag[i].Ausdruck[w][z]==';')
break;
if(eintrag[i].Ausdruck[w][z]== '('){
for(k=0;k<20;k++) {
fscanf(datei,"%c", &eintrag[i].Anmerkung[w][k]);
if (eintrag[i].Anmerkung[w][k] == ')') {
break;
}
}
if (eintrag[i].Ausdruck[w][z] == '\n')break;
}
}
}
}
for(i=0; i<anzahlzeile; i++){
printf("zeile %i", i+1);
for(w=0; w<10; w++){
printf("ausdruck = %c\n",eintrag[i].Ausdruck[w]);
printf("anmerkung = %c\n",eintrag[i].Anmerkung[w]);
}
}
//fclose
fclose(datei);
}
这就是我到目前为止所写的。我不知道这是正确的。
最佳答案
确切地说出您要执行的操作有点困难,但是如果我理解正确,则希望读取已发布的数据文件,忽略以'#'
开头的行,将其余的行读取为synonym[X].ausdruck
,如果该行包含(stuff)
,将'stuff'
读入synonym[X].anmerkung
。如果这不是您要尝试的操作,请澄清一下,我们很乐意为您提供进一步的帮助。 (注意:在C中,变量传统上是小写的,我在下面使用小写)
要实现上述内容,您只需要一个结构数组即可。您的Zeile
除了声明15 synonym
似乎没有其他用途(如果不是这样,请进一步解释)。要读取和解析每一行,对于synonym
的每个成员,您只需要2个足够大的字符数组。下面,我们创建了一个大小为synonym
(256)的MAXS
静态数组。 (您可以根据需要动态分配realloc
来处理未知数量的行,但是出于示例目的,我们将使用简单的静态声明)fgets
用于读取每一行。一个简单的辅助函数str_rmcrlf
从读取的每个字符串的末尾修剪newline
并返回其长度。不以'#'
开头的每一行都复制到synonym[idx].ausdruck
。 strchr
用于检查'('
的每一行。如果找到,则将(...)
的内容解析为sbuf
。如果转换成功,则将sbuf
复制到synonym[idx].anmerkung
。
试试看,让我知道您的要求是否与所描述的有所不同。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXS 256
#define MAXC 128
#define MAXW 64
typedef struct {
char ausdruck[MAXC];
char anmerkung[MAXW];
} synonym;
ssize_t str_rmcrlf (char *str);
int main (int argc, char **argv) {
char buf[MAXC] = {0};
synonym synonym[MAXS] = {{{0},{0}}};
size_t i, idx = 0;
FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
if (!fp) {
fprintf (stderr, "error: file open failed '%s'.\n", argv[1]);
return 1;
}
/* read each line in file until MAXS synonym elements filled */
while (idx < MAXS && fgets (buf, MAXC, fp))
{
if (*buf == '#') continue; /* skip beginning with '#' */
char sbuf[MAXW] = {0};
char *p = NULL;
ssize_t len = 0;
if ((len = str_rmcrlf (buf)) == -1) /* strip crlf, get length */
continue; /* continue on error */
/* (you should check for short-read here) */
strcpy (synonym[idx].ausdruck, buf); /* copy buf to ausdruck */
/* parse buf in anmerkung */
if ((p = strchr (buf, '('))) { /* check buf for '(' */
if (sscanf (p, "(%[^)\n]", sbuf)) /* read "(...)" */
strcpy (synonym[idx].anmerkung, sbuf); /* copy "..." */
}
idx++;
}
for (i = 0; i < idx; i++) {
printf ("\n synonym[%3zu].ausdruck : %s\n", i, synonym[i].ausdruck);
if (*(synonym[i].anmerkung))
printf (" synonym[%3zu].anmerkung : (%s)\n", i,
synonym[i].anmerkung);
else
printf (" synonym[%3zu].anmerkung :\n", i);
}
return 0;
}
/** stip trailing newlines and carraige returns by overwriting with
* null-terminating char. str is modified in place. The new length
* is retured on success, -1 otherwise.
*/
ssize_t str_rmcrlf (char *str)
{
if (!str) return -1;
if (!*str) return 0;
char *p = str;
for (; *p; p++) {}
p--;
for (; p >= str && (*p == '\n' || *p == '\r'); p--) *p = 0;
p++;
return (ssize_t)(p - str);
}
输出量
$ ./bin/fgets_struct dat/synonym.txt
$ ./bin/fgets_struct dat/synonym.txt
synonym[ 0].ausdruck : Kernfission;Fission;Kernspaltung;Atomspaltung;
synonym[ 0].anmerkung :
synonym[ 1].ausdruck : Wiederaufnahme;Fortfuehrung;
synonym[ 1].anmerkung :
synonym[ 2].ausdruck : wegfahren;wegfliegen;abfliegen;aufbrechen;abfahren;abduesen (ugs.);davonfahren;fortfahren;abreisen;
synonym[ 2].anmerkung : (ugs.)
synonym[ 3].ausdruck : Training;Kurs;Workshop;Weiterbildung;Seminar;Kursus;Bildungsmassnahme;Lehrgang;
synonym[ 3].anmerkung :
synonym[ 4].ausdruck : Zerlegung;Demontage;Entlassung;Abbau;
synonym[ 4].anmerkung :
注意:您必须提供足够的空间容纳整条线。您的上述数据将超出允许的
100
字符,从而导致部分读取或短读。您可以检查并处理指示的位置(或通过增加长度到128
来简单地为每行提供足够的存储空间)。将每一行拆分为单词
好的,注释现在可以帮助您阐明要完成的工作。在介绍实现之前,让我们先看一下C。 C语言比其他任何语言(汇编语言除外)更精确。 C语言中没有足够接近的语法。
尽管可能有很多方法可以找到解决方案,但就每一行代码而言,每一行中的每个字符都可以-是正确的-或错误的。您必须了解为什么需要每个字符及其作用。对于每个函数,无论是标准库中的函数,还是您编写的函数,您都必须知道该函数采用哪些参数,该函数对每个参数执行什么操作以及每个函数返回什么。
C为您提供了对构成程序的内存的逐地址访问,并且完全可以根据需要使用和管理该内存。它与C并没有紧密的联系。这就是C的力量和学习曲线的来源。您必须以这种详细程度和准确性来学习C。就像学习任何新语言一样,它需要工作,但是一旦您掌握了基础知识,天空便是极限。
学习C时,遇到一些您不了解的内容-查一下。将手册页的主要权限用于所使用的标准库。使用信誉良好的教程。在这里提问。但是要小心,在所谓的编程站点上张贴了很多代码,这完全是错误的。
所有编译器都为您提供了帮助您正确实现的工具。绝对最基本,最重要的是编译代码时编译器发出的警告。利用这一点。总是,总是在启用警告的情况下进行编译(例如
-Wall -Wextra
),直到代码没有警告地编译才接受代码(有一些例外,但它们非常非常罕见,在您遇到的任何情况下都不会遇到。不远的将来)话虽这么说,该代码的适当的编译字符串将类似于:
gcc -Wall -Wextra -O3 -o bin/fgets_struct_words fgets_struct_words.c
(将优化
-O3
替换为gcc上的-g
以启用调试符号)下面的代码使用相同的结构数组,但是在每个结构中有一个二维char数组,用作字符串数组。非常重要的是,将struct数组和每个成员初始化为
zero/nul
。这样可以确保所有字符串都将以nul终止。每个结构中的字符串数已添加为synonym[X].n
。这使您可以方便地按结构计算每行中的单词数。 strtok
用于将每一行分成每个;
或(
处的标记(单词)。代码仅读取每一行,跳过以
'#'
开头的行,对行进行标记,然后将每个单词存储在synonym[X].ausdruck[n]
中。如果单词以'('
开头,则将其放置在synonym[X].anmerkung[n]
中。通过两个示例并详细解释其工作水平,如果您有任何疑问,请告诉我:#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXS 256
#define MAXC 128
#define MAXW 64
#define MAXL 32
typedef struct {
char ausdruck[MAXW][MAXL];
char anmerkung[MAXW];
size_t n;
} synonym;
ssize_t str_rmcrlf (char *str);
int main (int argc, char **argv) {
char buf[MAXC] = {0};
synonym synonym[MAXS] = {{{{0}},{0},0}};
size_t i, j, idx = 0;
FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
if (!fp) {
fprintf (stderr, "error: file open failed '%s'.\n", argv[1]);
return 1;
}
/* read each line in file until MAXS synonym elements filled */
while (idx < MAXS && fgets (buf, MAXC, fp))
{
if (*buf == '#') continue; /* skip beginning with '#' */
char sbuf[MAXW] = {0};
char *p = NULL;
ssize_t n = 0, len = 0;
if ((len = str_rmcrlf (buf)) == -1) /* strip crlf, get length */
continue; /* continue on error */
/* copy each word in buf to ausdruck[n] or anmerkung[n] */
for (p = strtok (buf, " ;"); p; p = strtok (NULL, " ;\n")) {
if (*p == '(') { /* copy word in () to anmerkung */
if (sscanf (p, "(%[^)\n]", sbuf)) /* read "(...)" */
strcpy (synonym[idx].anmerkung, sbuf); /* copy "..." */
}
else /* copy word to array */
strcpy (synonym[idx].ausdruck[n++], p);
}
synonym[idx++].n = n; /* set n, increment idx */
}
for (i = 0; i < idx; i++)
{
putchar ('\n');
for (j = 0; j < synonym[i].n; j++)
printf (" synonym[%3zu].ausdruck[%2zu] : %s\n",
i, j, synonym[i].ausdruck[j]);
if (*(synonym[i].anmerkung))
printf ("\n synonym[%3zu].anmerkung : (%s)\n", i,
synonym[i].anmerkung);
else
printf ("\n synonym[%3zu].anmerkung :\n", i);
}
return 0;
}
/** stip trailing newlines and carraige returns by overwriting with
* null-terminating char. str is modified in place. The new length
* is retured on success, -1 otherwise.
*/
ssize_t str_rmcrlf (char *str)
{
if (!str) return -1;
if (!*str) return 0;
char *p = str;
for (; *p; p++) {}
p--;
for (; p >= str && (*p == '\n' || *p == '\r'); p--) *p = 0;
p++;
return (ssize_t)(p - str);
}
输出量
$ ./bin/fgets_struct_words dat/synonym.txt
synonym[ 0].ausdruck[ 0] : Kernfission
synonym[ 0].ausdruck[ 1] : Fission
synonym[ 0].ausdruck[ 2] : Kernspaltung
synonym[ 0].ausdruck[ 3] : Atomspaltung
synonym[ 0].anmerkung :
synonym[ 1].ausdruck[ 0] : Wiederaufnahme
synonym[ 1].ausdruck[ 1] : Fortfuehrung
synonym[ 1].anmerkung :
synonym[ 2].ausdruck[ 0] : wegfahren
synonym[ 2].ausdruck[ 1] : wegfliegen
synonym[ 2].ausdruck[ 2] : abfliegen
synonym[ 2].ausdruck[ 3] : aufbrechen
synonym[ 2].ausdruck[ 4] : abfahren
synonym[ 2].ausdruck[ 5] : abduesen
synonym[ 2].ausdruck[ 6] : davonfahren
synonym[ 2].ausdruck[ 7] : fortfahren
synonym[ 2].ausdruck[ 8] : abreisen
synonym[ 2].anmerkung : (ugs.)
synonym[ 3].ausdruck[ 0] : Training
synonym[ 3].ausdruck[ 1] : Kurs
synonym[ 3].ausdruck[ 2] : Workshop
synonym[ 3].ausdruck[ 3] : Weiterbildung
synonym[ 3].ausdruck[ 4] : Seminar
synonym[ 3].ausdruck[ 5] : Kursus
synonym[ 3].ausdruck[ 6] : Bildungsmassnahme
synonym[ 3].ausdruck[ 7] : Lehrgang
synonym[ 3].anmerkung :
synonym[ 4].ausdruck[ 0] : Zerlegung
synonym[ 4].ausdruck[ 1] : Demontage
synonym[ 4].ausdruck[ 2] : Entlassung
synonym[ 4].ausdruck[ 3] : Abbau
synonym[ 4].anmerkung :
捕捞指数
为了捕获
anmerkung
附加的单词,您只需要知道ausdruck
属于哪个索引。不需要整个单独的2D阵列。例如,您可以通过将aindex
添加到synonym
结构来捕获索引:typedef struct {
char ausdruck[MAXW][MAXL];
char anmerkung[MAXW];
size_t aindex;
size_t n;
} synonym;
然后,唯一需要捕获的代码更改就是换一行(并将
if
包裹在{}
中): synonym[idx].aindex = n > 0 ? n - 1 : n;/* set aindex */
在上下文中显示的内容适合此处:
if (*p == '(') { /* copy word in () to anmerkung */
if (sscanf (p, "(%[^)\n]", sbuf)) { /* read "(...)" */
strcpy (synonym[idx].anmerkung, sbuf); /* copy "..." */
synonym[idx].aindex = n > 0 ? n - 1 : n;/* set aindex */
}
}
现在,每当您填写
anmerkung
时,您还需要保存该单词之前的索引。您可以使用以下命令更改输出以验证索引: if (*(synonym[i].anmerkung))
printf ("\n synonym[%3zu].anmerkung : (%s) index: %zu\n", i,
synonym[i].anmerkung, synonym[i].aindex);
输出量
<snip>
synonym[ 2].ausdruck[ 0] : wegfahren
synonym[ 2].ausdruck[ 1] : wegfliegen
synonym[ 2].ausdruck[ 2] : abfliegen
synonym[ 2].ausdruck[ 3] : aufbrechen
synonym[ 2].ausdruck[ 4] : abfahren
synonym[ 2].ausdruck[ 5] : abduesen
synonym[ 2].ausdruck[ 6] : davonfahren
synonym[ 2].ausdruck[ 7] : fortfahren
synonym[ 2].ausdruck[ 8] : abreisen
synonym[ 2].anmerkung : (ugs.) index: 5
<snip>
另一注。您会看到以下代码:
synonym[idx].aindex = n > 0 ? n - 1 : n;
它使用
ternary
运算符设置synonym[idx].aindex
的值,而不是将值盲目地设置为n - 1
。 (与我们使用它打开命令行或默认为stdin
给出的文件的方式几乎相同)什么是
ternary
运算符?基本上,它是内联使用的简写if,then,else
。它显示为:(test) ? (if true code) : (if false code)
(但没有()
)。因此,再次查看该行。您会看到n > 0
是否将值设置为n - 1
,否则将其设置为n
(即0
)。关键是要防止如果行以aindex
开头(这将表示无效的数组索引),则将anmerkung
设置为负数。关于c - 将文件读入结构,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/34111117/