使用字符串和数组

时间:2017-04-27 00:52:36

标签: c arrays pointers c-strings

我正在创建一个程序,用于检查将从起始机场到目的地机场的可能航空公司(这些信息都将由用户输入)。我有一个包含所有航空公司#及其相应机场的文件。例如,10A, LIM, LAX具有航空公司编号(10A),起始机场(LIM)和目的地机场(LAX)。每行包含遵循航空公司#,原始机场(缩写)和目的地机场(缩写)格式的信息。

我将使C读取文件,它将使用fgets函数读取每一行,直到它到达与起始机场和目的地机场相匹配的行。然后,它将返回航空公司号码。如果没有,那么计算机将打印出没有航空公司有该航班。由于每一行都将被视为一个字符串,该字符串将存储在我称为str[10000]的字符数组中。我希望使用strcat功能存储航空公司号码。我想做的是strcat(str[0], str[1]),它会加入,例如我使用10A的示例是组合10(将存储在str [0]中)和A(将存储在str中) [1])。这种方法似乎不是出于某种原因而起作用。

我创建了函数void route(char *origin, char *destination, char *airline[])来打印出航空公司号码,但我不知道如何使用该阵列并将它们存储到*airline[]中。我还初始化为*airline[20]因为可能有几家航空公司从用户指定的起点到目的地。

我只是想确保我最终可以使用strcmp来比较用户为原始机场和目的地机场输入的内容,以便如果它与航空公司号码匹配则将报告。

请帮我处理字符串和数组。当我尝试编译并运行程序时,在进入原始机场和目的地机场后,我收到错误Abort Trap 6。我不知道为什么会这样。我将感谢任何人提供的任何帮助。提前致谢。

编辑以下是我认为主要问题来自......的功能

void route(char *origin, char *destination, char *airline[])
{
    char str[10000];

    while (fgets(str, sizeof(str), fp) != NULL)

    strcat(str[0], str[1]); // Combining the first element (10) with second element (A)
}   

请注意,这段代码仍然不完整,但到目前为止,我还是因为我被困住了。

编辑 10A不是航空公司编号的可能选择。它确实有三个元素,所有航空公司的选择只有两个元素,例如3A。

编辑我添加了使用fgets函数的行:while (fgets(str, sizeof(str), fp) != NULL)

1 个答案:

答案 0 :(得分:0)

继续发表评论(因为看起来你需要帮助才能让灯泡眨眼),让我们来看看你在做什么,而不是做,让你整理出来。首先让我们看一下你的宣言:

void route(char *origin, char *destination, char *airline[]);

void对于函数类型来说是一个可怕的选择,你需要某种方法来衡量函数的成功/失败(例如在你的情况下找到/未找到)。为type选择route,这样您就可以返回值,以在需要时指示成功/失败void有它的位置,例如就像在一个简单的函数中,只需打印输出,你可以在之前验证函数参数将它们传递给函数。否则,使用一种类型,您可以在其中检查返回值以确定函数是成功还是失败。这里有一个简单的int类型,在失败时返回01(或任何非零数字,甚至是负数)表示成功。

接下来,char *airline[]是一个指向char 类型的指针数组。这不是你想要传递像3A这样的字符串的字符串,它是一个类型为char 的数组(在传递时将转换为指向char * 的指针作为函数参数)或sting文字,它只是指向char 的指针。所以你实际上想要char *airline

接下来,除非您将fp声明为全局文件流指针(糟糕的主意),否则您需要将FILE *fp作为参数传递给route。将这些信息放在一起,您对可用route的声明可以是:

int route (char *origin, char *dest, char *airline, FILE *fp);

根据您在问题中描述的内容,您需要使用fgets,但目前尚不清楚您实际可用于解析airlineorigin和{{1}的内容} destinationstr填充。因此,让我们假设您没有其他功能可以用来分隔字符串,并且让我们使用始终可用的两种基本方法(数组索引指针算术)从fgets解析airlineorigindestination

这是从str开始并走一个指针(或使用数组索引)来检查每个字符的值并根据需要分配字符(解析单词)的基本方法,直到你有您需要的所有数据,或者到达str的末尾(您必须防止这两种情况)。

在处理字符串时,由来记录你的位置,并在合理的程度上预测接下来会发生什么,这样你就可以测试每个角色(对于你是什么)需要,以及字符串的结尾),将它保存在需要保存的地方,或继续将其保存在其他地方。执行此操作时,您需要跟踪已保存到每个位置的字符数(例如,分隔字符数组,如strarlnorg以进行比较您正在寻找的dstairlineorigin,以确保您不会在任何数组的末尾写入,或者分配内存块,记住保存{{1在每个数组的末尾或分配的内存块中保存destination nul-byte nul-terminating character )以使每个< em>有效字符串。 (了解+1 char nul-byte的字符值只有'\0',因此您可以使用'\0'或简单0来终止字符串)

让我只提供一个注释示例,逐步帮助您理解逻辑(和思想水平),而不是逐步解释可用'\0'函数的每一行。并且理解在C中做任何事情所需要的,你可以完全控制你如何使用内存,并且你有责任确保你正确使用它 - 以强大的力量来承担很大的责任)。通过以下工作,如果您需要任何特定部分的帮助,请告诉我。

我故意在示例中同时使用数组索引指针算法,但对于此类型的正常实现,我更喜欢指针算法,原因在于评论。以下所有方法都可以通过多种不同方式完成,例如使用0来简化读取和解析,或者使用routefscanf来解析填充strtoksscanf。这些函数只是通过将指针(或一对指针)向下移动来帮助您完成手动执行的操作。

我已经验证了str中传递给fgets的参数作为示例,但您通常希望在调用此函数之前在调用函数(此处为route)中执行此操作route。有了这个,这里有一个可用的main的例子,它将逐步输入包含格式为:

的行的输入文件
route

route必须出现在每个标识符的末尾,因为它当前已编码,但空格的数量并不重要。airline, origin, destination /* e.g. '3A, KOCH, KEGE' */ 也可以正常工作。你有完全控制这一点,只需更改每个角色的测试,您就可以完全消除commas要求,只需找' 3A, KOCH, KEGE'来构成每个单词 - 这一切都取决于你。)

','将读取数据文件中的每一行,0-9, a-z, A-Z将各个标识符解析为routefgetsarln,以便与{{1}进行比较}},orgdst传递给airline,如果找到匹配则返回origin,或者如果找不到匹配则返回destinationroute的示例:

1

注意: 0基本上会做同样的事情三次。从每个标识符的开头开始,将每个字符读入正确的数组,直到找到route(或* nul-byte), nul-terminate 您的新数组,然后移动到int route (char *origin, char *dest, char *airline, FILE *fp) { /* validate parameters - you can do this before calling route */ if (!origin || !*origin) { fprintf (stderr, "error: origin 'NULL' or empty.\n"); return 0; } if (!dest || !*dest) { fprintf (stderr, "error: dest 'NULL' or empty.\n"); return 0; } if (!airline || !*airline) { fprintf (stderr, "error: airline 'NULL' or empty.\n"); return 0; } if (!fp) { fprintf (stderr, "error: fp not open for reading.\n"); return 0; } char str[LINE] = ""; while (fgets (str, LINE, fp)) /* for each line in the input file */ { char org[PARTS] = "", dst[PARTS] = "", arln[PARTS] = "", *o = org, *d = dst, *a = arln, *s = str; size_t n; /* check for trailing '\n' included by 'fgets' indicating * complete line read into str, then remove '\n' by overwriting * with nul-terminating character. */ n = strlen (str); if (str[n - 1] == '\n') str[--n] = 0; /* read airline flight from str into arln, will skip leading * whitespace copying all other chars up to first ',' or '\0'. * (you can also use strtok to 'tokenize' the line) */ /* you can either use array indexing */ for (n = 0; n < PARTS - 1 && s[n] && s[n] != ','; n++) { if (s[n] == ' ') continue; /* skip space */ a[n] = s[n]; } a[n] = 0; /* nul-terminate arln (already done, but...) */ s += n; /* indexing wont advance 's', advance to char after 'arln' * (to the ',') to start looking for beginning of 'org'. */ /* or use pointer arithmetic (cleaner as 's' is advanced) * * for (n = 0; n < PARTS - 1 && *s && *s != ','; n++, a++, s++) { * if (*s != ' ') continue; * *a = *s; * } * *a = 0; */ /* add checks to validate 'arln' length here if desired, and the same * following filling 'org' and 'dst' if desired */ /* compare arln to airline */ if (strcmp (arln, airline) != 0) continue; /* doesn't match, get next line */ /* find start of origin (org) in str (using pointer arithmetic) * skipping forward until you find next '0-9', 'a-z' or 'A-Z' * (you can use while (*s && isalnum (*s)) from ctype.h instead) */ while ( *s && ( (*s < '0' || '9' < *s) && (*s < 'a' || 'z' < *s) && (*s < 'A' || 'Z' < *s))) s++; if (!*s) { /* validate you are not at end of str */ fprintf (stderr, "error: no valid chars follow airline in str.\n"); return 0; } /* fill org ICAO from str */ for (n = 0; n < PARTS - 1 && *s && *s != ','; n++, o++, s++) *o = *s; *o = 0; /* compare org to origin */ if (strcmp (org, origin) != 0) continue; /* doesn't match, get next line */ /* find start of destination (dst) in str (using pointer arithmetic) * skipping forward until you find next '0-9', 'a-z' or 'A-Z' * (you can use while (*s && isalnum (*s)) from ctype.h instead) */ while ( *s && ( (*s < '0' || '9' < *s) && (*s < 'a' || 'z' < *s) && (*s < 'A' || 'Z' < *s))) s++; if (!*s) { /* validate you are not at end of str */ fprintf (stderr, "error: no valid chars follow origin in str.\n"); return 0; } /* fill dst ICAO from str */ for (n = 0; n < PARTS - 1 && *s && *s != ','; n++, d++, s++) *d = *s; *d = 0; /* compare dst to destination */ if (strcmp (dst, dest) == 0) goto found; /* match for airline, origin, destination found */ } return 0; /* return 0 - indicating no route found */ found: return 1; /* return 0 - indicating route found */ } 中的下一个字符,跳过所有内容,直到找到route(开始下一个标识符),然后重复。

使用它的一个简短例子是:

','

示例输入文件

str

示例使用/输出

0-9, a-z, A-Z

通过这个例子,请确保你理解这一切,如果你没有(在你做出合理的搜索以回答基本语法,等等问题后,请告诉我)