【问题标题】:Parsing string with multiple delimiters使用多个分隔符解析字符串
【发布时间】:2016-02-16 21:36:55
【问题描述】:

我怎样才能像这样解析文本文件: 免责声明:我不能假设我知道文本文件的内容这只是一个示例文本文件

10X16 de4 dw9 ds11 g10,7 M3,4 h6,5 p2,2 M8,5 G2,10
12X20 de7 dw10 dn13 g9,10 M7,8 h6,5 p2,2 M8,5 G2,10

这个文本文件的意思是有一个房间,尺寸为10X16,东墙上有一扇门de4在第四位置,g10,7表示位置10Y有一个小金子和7X...我不想存储任何字母,这些字母只是为了告诉我正在读取的数字的用途。我想将数字存储到int变量中,根据它是什么:黄金、怪物、药水等。

我需要将10 存储为Y 值和16 作为X 值,并且维度之后的其他元素存储在不同的变量中。

这是我的代码:

int main(int argc, char *argv[]) {
    //open file and read
    FILE *file = fopen(argv[1], "r");
    char line[150];
    char *dim;
    int X = 0;

    while (fgets(line, 150, file) != NULL) {
        dim = strtok(line, "X");
        X = atoi(dim);
        printf("%d\n", X);

        //parse other elements here?
        ...
    }
    fclose(file);
    return 0;
}

例如,我希望将变量 char *roomY 中的 10char *roomX 中的 164 存储在变量 char *eastDoor 中,这些变量稍后将全部转换为 int 值.

g10,7 这样的元素我希望将10 存储为Y 值和7 作为该元素的X 值。

我还应该补充一点,应该使用字母来确定值是什么。 例如可以使用if (string[i] = "d") 路径。

我尝试使用strtok(roomY, "X") 获取X,然后使用int Y = atoi(roomY)char 转换为int 值。这仅适用于10,但文件的其余部分无法正确解析。有没有更有效的方法来做到这一点?

【问题讨论】:

  • 看看sscanf
  • sscanf 不能帮助我从像 g7,10 这样的元素中解析 7 和 10,或者我不确定你的建议是什么。
  • 为什么不呢? sscanf("g7,10", "g%d,%d", &a, &b) 会给你 a=7 和 b=10。
  • 对不起,我应该指定我不能假设文本文件的内容
  • 我确信数据可以改变。格式一致吗?如果格式发生变化,那么很可能没有多少代码可以解决问题。

标签: c file parsing


【解决方案1】:

我认为解析文件最简单的方法是使用strtok" " 来获取基本令牌,然后使用sscanf 根据其标识符评估每个令牌。

char* tok = strtok( line, " " );
/* handle first token */
int x, y;
sscanf( tok, "%dX%d", &x, &y );

while( tok = strtok( 0, " " ) )
{
   /* handle token depending on text */
   switch( *tok )
   {
       case 'M' : 
       {
           int mx, my;
           sscanf( tok, "M%d,%d", &mx, &my );
           break;
       }
       // ...
   }
}

请不要说这只是解决方案的草图。您应该将 switch 移动到一些 eval_token 函数中,以及每个案例。

【讨论】:

    【解决方案2】:

    我对使用 C 进行字符串解析的一般建议:

    不要尝试在一个大函数中处理所有内容,使用嵌套循环、指针、不同解析模式的标志等等。这将导致错误、访问冲突和难以理解的代码。

    而是尝试将问题分解为更简单的任务(函数),例如拆分字符串、替换特定字符或创建子字符串。然后结合这些函数得到想要的结果。

    或者也许尝试找到一个现有的用于字符串操作的库。

    【讨论】:

      【解决方案3】:

      是的。您可以使用 strtok。秘密在于分隔符字符串可以包含多个分隔符。

      dim = strtok(line, "X ,");
      

      通常我会告诉人们从 strtok 尖叫着跑,因为在我看来它有一些奇怪的行为。在你的情况下,我认为这可能是合理的。

      这个可以使用“X”、空格和逗号作为分隔符。我希望扫描 17 个值。

      12X20 de7 dw10 dn13 g9,10 M7,8 h6,5 p2,2 M8,5 G2,10    
      

      这个不一样。注意三重逗号。 Strtok 假设那里没有价值。所以我希望扫描 15 个值。这可能是也可能不是你需要的。如果您尝试解析 csv 文件,strtok 将是错误的方法。

      12X20 de7 dw10 dn13 g9,10 M7,8 h6,5 p2,,,5 G2,10
      

      【讨论】:

      • 好的,这很有帮助,但问题是我不想存储字母,我希望我的程序读取字母,以便它知道存储数字的变量是什么
      • Strtok 只是遍历输入集中的字符串。你对每个字符串做什么取决于你。你的问题的关键部分是把所有的部分都拉出来。关于多个分隔符的小细节应该有助于您前进。
      • 如何将它们存储在单个变量中?即 g9,10 将是 int goldY = 9 和 int goldX = 10
      • 这真的超出了问题的范围。
      • 我明白,但那是我最初提到的问题,虽然你的 strtok 回答非常有帮助,但如果你能帮助我解决我的问题,那将非常有帮助对我来说是最棘手的部分
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-02-27
      相关资源
      最近更新 更多