c - 如何正确地将一定数量的多个字符的文件读入 C 中的 char 数组?

标签 c string

我是编程新手,我不确定如何解决这个问题。我试着做 %8s ... %52s 但它没有考虑到分隔符应该占用子字符串中的空间。因此,如果我尝试扫描 8 个空格,一个长度为 5 的单词、一个空格和另一个长度为 8 的单词,它将获取第一个字母字符串而不是空格。这是一次从文件中读取一行,但将其分解为子字符串,其中每个子字符串都放入一个唯一的数组中。 例如:

        Word AnotherW

第一个数组将包含 Word,而不是 (8 个空格)。

    char firCol[8];                   //first 8 characters including delimiters
    char space[1] = {' '};            //guaranteed space
    char secCol[1] = {' '};           //space or '+'
    char thirCol[7];      //word of length 7 but if shorter includes delitimers
    char forCol[1] = {' '};           //guaranteed space
    char fifCol[10];                  //sames of 7 but length 
    char comm[52];                    // length 52 char and delimitrer

    memset(firCol, ' ', 8);
    memset(thirCol, ' ', 7);
    memset(comm, ' ', 52);

    f = fopen(argv[1], "r");                                                           

    memset(info, 0, sizeof(struct Account) * TABLE_SIZE);
            //Initialize the array, set all indices equal 0 

      while(EOF != fscanf(f, "%8c %1c %1c %7c %1c %10c %52c", firCol, space, secCol, thirCol, forCol, fifCol, comm))
      {
        pass1(info, firCol, space, secCol, thirCol, forCol, fifCol, comm);
      }




/******************************/
/***MORE    INFO    ADDED******/
/******************************/


    Col 1-8    label optional
    Col 9      blank
    Col 10     + optional
    Col 11-17  mneumonic
    Col 18     blank
    Col 19     #, @, =  ... optional
    Col 20-29  (operand) label, register, ',',X optional  ...
    Col 30-31  blank
    Col 32-80  comments optional (NO PERIOD REQUIRED)


    ADDRES    START    100                               
    . tests pc forward addressing
    . tests base addressing
    . tests pc backward addressing
    NOW      +LDB     #BEGIN              load base register 
    XXX       BASE     BEGIN              tell assembler  
    YYY       LDA      BE                 A <- (m..m+2)    
    EN        RESW     4                  
    BE        WORD     2                              
    BEGIN     RESW     1
    JUNK      RESW     2200                              
    THERE     RESW     1                              
    ZZZ       LDA      JUNK                               
    MMM       STA      THERE                              
              END      NOW          


    RESULTS:

    100     ADDRES    START    100                               
    . TESTS PC FORWARD ADDRESSING
    . TESTS BASE ADDRESSING
    . TESTS PC BACKWARD ADDRESSING
    100    NOW      +LDB     #BEGIN              LOAD BASE REGISTER 
    104    XXX       BASE     BEGIN              TELL ASSEMBLER  
    104    YYY       LDA      BE                 A <- (M..M+2)    
    107    EN        RESW     4                  
    113    BE        WORD     2                              
    116    BEGIN     RESW     1
    119    JUNK      RESW     2200                              
    1ae1   THERE     RESW     1                              
    1ae4   ZZZ       LDA      JUNK                               
    1ae7   MMM       STA      THERE                              
    1aea                END      NOW                              

    Table Location      Label      Address      Use Csect
    135 0                   BE          113         main    main
    147 0                   EN          107         main    main
    231 0                   MMM        1ae7         main    main
    244 0                   NOW        100          main    main
    264 0                   XXX        104          main    main
    267 0                   YYY        104          main    main
    270 0                   ZZZ        1ae4         main    main
    312 0                   JUNK          119       main    main
    357 0                  BEGIN         116        main    main
    376 0                  THERE         1ae1       main    main
    435 0                  ADDRES       100         main    main

最佳答案

首先,正确的方法:

#include <stdio.h>

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

  //TODO: Name this variables better. I cannot stress how important naming this is
  char firCol[9];        //first 8 characters including delimiters
  char plusFlag;           //space or '+'
  char thirCol[8];       //word of length 7 but if shorter includes delitimers
  char fifCol[10];       //sames of 7 but length 
  char comm[53];         // length 52 char and delimitrer

  FILE* f;  //Don't forget variables. And when asking questions with code, it's best to include everything

  //Don't worry about initializing the strings. In general, initializing variables is a good idea, but these will be clobbered.

  f = fopen("file.txt", "r");                                                    
  //Ah, dead code. It might have been something at some point. But it was killed. Now it's corpse litters the field of battle.
  //memset(info, 0, sizeof(struct Account) * TABLE_SIZE);                                  //Initialize the array, set all indices equal 0 

  //the spaces in the file are eaten by the spaces in the string literal
  //The size of the strings can vary, but the number in %8s is the maximum. It's a good safety precausion.
  // %*c eats a character and throws it away. We do this because there might be one or two whitespaces. The second of which may be important. If we put a whitespace in the string literal, it would have eaten both, throwing off the rest of the command.
  //The %c is always just one character. You don't want to read in a string for that + symbol, as it isn't terminated by a null character. %1s would work... but no.  
  //The %c is tied to &plusFlag.   The ampersand indicates the address of the variable.  The other variables are arrays, and act like the address of the first character in the array.  
  while(fscanf(f, "%8s%*c%c%7s %9s %52s", firCol, &plusFlag, thirCol, fifCol, comm) != EOF)
  {
    printf("%s %c %s %s %s\n", firCol, plusFlag, thirCol, fifCol, comm);
  }
  return 0;
}

对于不同程度的“妥当”。我的意思是,您真的确定数据格式正确吗?该文件中甚至还有数据?有文件吗?仔细检查所有可能发生的事情是至关重要的 DO-178c 代码和高中演示之间的区别。那和一大堆文档。

从技术上讲,您所做的应该有效。你的 fscanf 中只有额外的空间。所以它扫描了 8 个字符,将它们放入 firCol,然后吃掉一个你认为会进入 space 的空格,然后将 + 放入 space。尝试:

fscanf(f, "%8c%1c%1c%7c%1c%10c%52c", firCol, space, secCol, thirCol, forCol, fifCol, comm))

这确实从文件中读取数据并将其放入您的变量中……但我不会称其为“正确的”。如果你想使用字符串,你会发现如果你用 null 终止它们,它与编程世界的其他部分更兼容。这符合……呃……常识。虽然剥猫皮的方法有上百万种,但与所有其他程序员、库和 API 一起效仿会让你的生活更轻松。

C 中的字符数组,也称为字符串,需要在它们的末尾有一个空终止字符 '\0''\0' 与二进制值 0 相同,但与 ascii 字符 '0' 不同。

注意引号。在 C 中,单引号中的任何内容都是 char。 'a'、'b'、'9'、'0',以及诸如 '\n'、'\0' 或 '\b' 之类的命令字符。引号中的任何内容都是字符串文字。 “这是一个字符串文字”char 字符几乎只是在 ascii 表上执行查找。另一方面,字符串表现得有点古怪,有很多陷阱让人们学习这门语言。使 C 字符串更易于处理是催生其他语言的主要力量之一。

看起来你想把这一切都推到一个结构中。你可以这样做:

//Outside of main
typedef struct 
{
  char firCol[9];        //first 8 characters including delimiters
  char plusFlag;           //space or '+'
  char thirCol[8];       //word of length 7 but if shorter includes delitimers
  char fifCol[10];       //sames of 7 but length 
  char comm[53];         // length 52 char and delimitrer
} DataFromFile_t;


int main(int argc, char **argv)
{
  DataFromFile_t  dataFromFile;
  . . .
  fscan(f,"%s ...", dataFromFile.firstCol);

让我看看还有什么......

  • [关于正确缩进的一般愤怒咆哮。]我的意思是两个空格,而不是异教徒一直喋喋不休的这种“制表符”业务。
  • 显示示例中所有代码的重要性。
  • 在问题中说明您拥有什么、您将得到什么以及您希望得到什么。我实际上不确定您认为出了什么问题,我只是在这里猜测。
  • 不要过分强调什么是“适当的”。如果它 gits'er'done,通常就足够了。

关于c - 如何正确地将一定数量的多个字符的文件读入 C 中的 char 数组?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29130413/

相关文章:

java - 将 .txt 文件的内容读入二维字符串 ARRAYLIST

c - 基于(堆栈/注册)的虚拟机如何处理不同的数据类型

c - 对链表进行基数排序

c - c中的变量声明为全局或封装它们并使用getter和setter

c++ - 字符串 C++ 操作

string - Xcode 6.1 和 Swift - 文本字段输入字符串到整数以进行基本数学

c++ - 在 C++ 中取消读取文件

c - 我想将 gdb 用于一个 c 文件,该文件具有类似 #include "config.h"的头文件?

C++ "cin"只读取第一个字

java - 替换字符串中的术语