C - 从文件中读取并使用多维数组

时间:2017-11-25 02:29:23

标签: c arrays file multidimensional-array

第一次使用本网站。有人建议我来这里。所以,我很快就会完成一项任务,而且我很难编写代码。我尽我所能地完成了它,一切似乎都是为了我,但是当我运行程序时,无论我输入什么,结果都不会改变。作业是:

编写一个C程序,从一个名为“input.txt”的文件中读取有关5个工作人员的信息。每一行输入都会 分别包含两个值,一个员工ID和员工的月薪。

假设输入文件中的数据以本示例中所示的格式存储。注意:出于测试目的,可能不一定使用以下数据。它只是让您了解数据的格式:

input.txt的示例内容: 2000年10月 20 6800 30 9700 40 1500 50 8000

将员工信息存储到2D阵列中。假设数据类型如下:id(整数数据类型)和收入(整数数据类型)。

读取信息并将5个员工记录存储到2D阵列中。

使用打印工人所有收入总和的函数。

创建另一个功能,打印收入超过5000美元的工人数量 收入超过5000美元的每个工人的身份和收入。

我的代码如下:

  #include <stdio.h>
#include <stdlib.h>

int employeeID, salary;
int id[5][2], income[5][2];
int sum();
int greater();
FILE *worker;

int main()
{


    worker=fopen("input.txt", "w");
        printf("Enter Employee ID and Salary:\n");
    for(employeeID=0;employeeID<5;employeeID++){
        for(salary=0;salary<2;salary++){
            scanf("%d", &id[employeeID][salary]);
        }
    }
    for(employeeID=0;employeeID<5;employeeID++){
        for(salary=0;salary<2;salary++){
            fprintf(worker,"%d", &id[employeeID][salary]);
        }       
    }
        fclose(worker);

    worker=fopen("input.txt", "r");
        while(!feof(worker)){
            for(employeeID=0;employeeID<5;employeeID++){
                for(salary=0;salary<2;salary++){
                    fscanf(worker,"%d", &income[employeeID][salary]);

                }
            }
        }
    sum();
    greater();
}
int sum()
{
    int totalincome, totalsum;
    int income[5][2];

totalsum=income[0][1]+income[1][1]+income[2][1]+income[3][1]+income[4][1];
totalincome=printf("\nSum of all workers incomes:$%d\n");
    return totalincome;
}
int greater()
{
    int employeeID, salary;
    int income[5][2];
    int num=0;
    for(employeeID=0;employeeID<5;employeeID++){
        for(salary=0;salary<2;salary++){
            if(income[employeeID][salary+1]>5000){
                num++;
            }
        }
    }
    printf("\nWorkers that have income greater than $5000:\t");

        if(income[0][1]>5000)
        {
            printf("\nEmployee ID:%d  Salary: $%d", income[0][0], income[0][1]);
        }

        if(income[1][1]>5000)
        {
            printf("\nEmployee ID:%d  Salary: $%d", income[1][0], income[1][1]);
        }       

        if(income[2][1]>5000)
        {
            printf("\nEmployee ID:%d  Salary: $%d", income[2][0], income[2][1]);
        }

        if(income[3][1]>5000)
        {
            printf("\nEmployee ID:%d  Salary: $%d", income[3][0], income[3][1]);
        }

        if(income[4][1]>5000)
        {
            printf("\nEmployee ID:%d  Salary: $%d", income[4][0], income[4][1]);
        }

    return 0;   //End of Program
}

我知道这有很多东西要读,但我真的很感激任何人的帮助。我真的很挣扎。谢谢。

2 个答案:

答案 0 :(得分:2)

对于初学者来说,除非绝对需要,否则避免使用全局变量(这在您第一次学习C时几乎不会)。相反,在main()中声明所需的变量,并将其作为参数传递给任何函数。

您最初通过无法验证返回或其中之一来邀请未定义的行为

worker=fopen("input.txt", "w");

        scanf("%d", &id[employeeID][salary]);

您必须验证代码的所有输入方面。否则,您不知道您实际上是在读取文件(或NULL流指针)并且未能验证scanf的返回是否完全不知道是否有效转换发生了输入匹配失败。

您从文件读取到2D数组,然后执行以下操作?

for(employeeID=0;employeeID<5;employeeID++){
    for(salary=0;salary<2;salary++){
        fprintf(worker,"%d", &id[employeeID][salary]);
    }       
}

您无法使用id[employeeID][salary] 格式说明符打印 "%d"地址 - 调用未定义的行为 。 (&不应该在那里......)此外,为什么你试图将值写回到刚才用scanf的前一组嵌套循环中读取它们的文件? ?这样做会删除值之间的所有空格,留下一长串数字。

您只需一个二维数组。它会在第一列中保留employeeid,在每行的第二列中保留salary

让我们看看如何正确执行此操作,首先,不要在代码中使用幻数硬编码文件名

/* if you need constants, #define them or use an enum */
enum { SALCOL = 1, NCOL = 2, NROW = 5, HISAL = 5000 };

main()接受参数的正确定义是:

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

您可以将文件名作为第一个参数传递给您的程序,并避免在代码中对"input.txt"进行硬编码。

main()中定义您的变量,打开您的文件(如果没有给出filname,此代码也默认从stdin读取)并始终验证该文件已打开读数。

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

    int rows = 0,   /* row index */
        cols = 0,   /* col index */
        wrkrs[NROW][NCOL] = {{0}};  /* 2d array for workers */
    FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;

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

您必须跟踪您阅读的数据行数。您不能仅仅依赖于文件中存在一定数量的值,这些值恰好与您在代码中放置的常量相匹配。跟踪列索引和行索引并根据需要重置以填充2D数组:

    /* read values while rows < NROW */
    while (rows < NROW && scanf ("%d", &wrkrs[rows][cols]) == 1)
        if (++cols == NCOL) {   /* increment and check col = NCOL */
            cols = 0;           /* reset col to zero */
            rows++;             /* increment row index */
        }

剩下的就是关闭你的文件并输出所有工人,然后输出那些HISAL5000)作为工资的工人:

    if (fp != stdin) fclose (fp);   /* close file if not stdin */

    prnwrkrs (wrkrs, rows);             /* output all workers */
    prnhighwrkrs (wrkrs, rows, HISAL);  /* output workes making HISAL */

    return 0;
}

对于您的打印功能,您需要传递工人2D数组和数据行数(可能小于您的预期)。 注意:您可以将一个二维数组作为int array[][NCOL]传递,该数组将转换为指向NCOL数组的指针,这意味着您也可以将工作程序作为int (*array)[NCOL]传递给反映实际接收的功能。处理它的一种方法是:

/* print all workers in 2d array 'a' with `rows' rows.
 * note: a can be passed as 'a[][NCOL] as well
 */
void prnwrkrs (int (*a)[NCOL], int rows)
{
    printf ("\nAll workers:\n");        /* print heading */
    for (int i = 0; i < rows; i++) {    /* loop over each row */
        printf ("  worker[%d] : ", i);  /* output worker[] label */
        for (int j = 0; j < NCOL; j++)  /* loop over each col */
            printf (" %6d", a[i][j]);   /* output integer value */
        putchar ('\n');                 /* tidy up with '\n' */
    }
}

要处理HISAL工人,你只需传递一个额外的参数,薪水来比较工人工资(注意:,因为你已经宣布了常量,你可以省略传递工资和只需使用常量进行比较,但为什么不使函数显示工作者比你想要传递给函数的任何薪水更有用,例如

/* print worker earning more than 'sal'
 * same as prnwrkrs, but passes additional parameter 'sal'
 * for comparison. Compre to salary and print if greater.
 */
void prnhighwrkrs (int (*a)[NCOL], int rows, int sal)
{
    printf ("\nWorkers earning %d or more:\n", sal);
    for (int i = 0; i < rows; i++) {
        if (a[i][SALCOL] >= sal) {          /* compare with 'sal' */
            printf ("  worker[%d] : ", i);  /* output if greater */
            for (int j = 0; j < NCOL; j++)
                printf (" %6d", a[i][j]);
            putchar ('\n');
        }
    }
}

完全放弃,您可以执行以下操作:

#include <stdio.h>

/* if you need constants, #define them or use an enum */
enum { SALCOL = 1, NCOL = 2, NROW = 5, HISAL = 5000 };

/* print all workers in 2d array 'a' with `rows' rows.
 * note: a can be passed as 'a[][NCOL] as well
 */
void prnwrkrs (int (*a)[NCOL], int rows)
{
    printf ("\nAll workers:\n");        /* print heading */
    for (int i = 0; i < rows; i++) {    /* loop over each row */
        printf ("  worker[%d] : ", i);  /* output worker[] label */
        for (int j = 0; j < NCOL; j++)  /* loop over each col */
            printf (" %6d", a[i][j]);   /* output integer value */
        putchar ('\n');                 /* tidy up with '\n' */
    }
}

/* print worker earning more than 'sal'
 * same as prnwrkrs, but passes additional parameter 'sal'
 * for comparison. Compre to salary and print if greater.
 */
void prnhighwrkrs (int (*a)[NCOL], int rows, int sal)
{
    printf ("\nWorkers earning %d or more:\n", sal);
    for (int i = 0; i < rows; i++) {
        if (a[i][SALCOL] >= sal) {          /* compare with 'sal' */
            printf ("  worker[%d] : ", i);  /* output if greater */
            for (int j = 0; j < NCOL; j++)
                printf (" %6d", a[i][j]);
            putchar ('\n');
        }
    }
}

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

    int rows = 0,   /* row index */
        cols = 0,   /* col index */
        wrkrs[NROW][NCOL] = {{0}};  /* 2d array for workers */
    FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;

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

    /* read values while rows < NROW */
    while (rows < NROW && scanf ("%d", &wrkrs[rows][cols]) == 1)
        if (++cols == NCOL) {   /* increment and check col = NCOL */
            cols = 0;           /* reset col to zero */
            rows++;             /* increment row index */
        }

    if (fp != stdin) fclose (fp);   /* close file if not stdin */

    prnwrkrs (wrkrs, rows);             /* output all workers */
    prnhighwrkrs (wrkrs, rows, HISAL);  /* output workes making HISAL */

    return 0;
}

示例输入文件

$ cat dat/workers.txt
 10 2000 20 6800 30 9700 40 1500 50 8000

示例使用/输出

$ ./bin/workers <dat/workers.txt

All workers:
  worker[0] :      10   2000
  worker[1] :      20   6800
  worker[2] :      30   9700
  worker[3] :      40   1500
  worker[4] :      50   8000

Workers earning 5000 or more:
  worker[1] :      20   6800
  worker[2] :      30   9700
  worker[4] :      50   8000

C不是一种语言,你可以猜测代码应该是什么,编译它,失败,用你的下一个猜测改变它,再次编译,失败......你必须花时间来验证每一块这个难题,知道你正在处理什么值,它们所处的索引,以及如何在代码中正确使用每个函数。您可以通过检查man function查看您使用的每个标准库函数,直到您知道它们为冷 - 然后您仍然会查看man function以确保它们。

仔细看看。了解代码执行操作的原因并询问您是否还有其他问题。

答案 1 :(得分:0)

此处不需要两个 2D阵列。您只需要一个,也许称之为employeeInfo维度:5名员工和2条信息[一行用于员工ID号,另一行用于收入] employeeInfo[ numberOfEmployees ][ infoTypes ]

| id0 | id1 | id2 | id3 | id4 | &lt;&lt; - employeeID&#39; s

| $ s0 | $ s1 | $ s2 | $ s3 | $ s4 | &lt;&lt; - 员工的薪水

(抱歉格式不佳^)

所以现在我们想要将文件中的数字读入其中,因此我们需要通过将r传递给fopen()函数来打开文件进行读取:

worker = fopen("input.txt", "r");  //open file for reading
// Since we know exactly how many employees there are
// we can read precisely that many times in a double for loop: 
//  but the hardcoded literals work better as variables in the future
//  (see the comments in the greater() function below for ideas)          
for (int employee = 0; i < 5; employee++) //five employees
{
    for (int infoType = 0; info < 2; infoType++) //two pieces of info per employee
    {
        int info; // for storing the ID/SALARY
        fscanf(worker, " %d", &info); // read the next value  
        employeeInfo[employeeID][infoType] = info ; // store in 2d array(our table)
    }
} 
fclose(worker);

好的,现在我们的employeeID数组(或表)已满!我们现在可以总结收入并打印总数:

int sum() # or void sum() unless you have future plans for this
{
    //int income[5][2]; this is empty and not needed. 
    int totalsum; //second variable not needed

    // global scope of the first 2d array means that you can access it here.

    totalsum = 0; // start at 0 and add incomes as we go
    for(int employee = 0; employee < 5; employee++)
    { 
      totalsum += employeeInfo[employee][1];
    }
    // the above for loop has the advantage that we can easily sum for more
    // employees
    //totalsum=income[0][1]+income[1][1]+income[2][1]+income[3][1]+income[4][1];
    //now we're printing totalsum
    printf("\nSum of all workers incomes:$%d\n", totalsum); 

    return totalsum; // this is not used but this is returning the sum
}

sum()函数错误地做了三件大事:

  1. 忘记范围的工作原理: 它声明了一个新的数组income,其值与全局范围内的收入无关&#39;阵列。既然你宣布了第一个收入&#39;在main函数之外的数组中,它位于全局范围中,这意味着它可以从任何地方访问。无需重新宣布。

  2. Printf()错误:

    在printf()的代码中实际上有两个错误。首先,您可以使用格式说明符(如%d)为它打印要使用逗号分隔的格式说明符(如printf("some text: %d %c", myInteger, myChar))的变量名称。像这样:void

    要注意的另一件事是printf()将打印到std out(在大多数情况下是控制台),但如果你将它存储在一个变量中,就像你所做的那样,你存储的是它的内部返回值,这实际上是打印的字符数。请参阅此问题:Return value of printf() function in C

  3. 不归还总和:

    我猜你认为总收入会有总数,但正如所提到的,printf()并没有返回打印的内容。另请注意,sum()返回的内容未在main函数中存储或使用。在这种情况下,它也可以是int greater() { // int income[5][2] is empty and not needed // all the info is read into the globally declared 2D array (employeeInfo) // by the time greater() is called int employeeID; // , salary <<--not needed // but it is good style to avoid "magic numbers" // like the hard-coded '5' or '1' in the loop below // we could instead define static constants before main // for example: // static const int HIGH_SALARY= 5000 // or if you need to use the "magic numbers" as an array dimension: // enum {MAX_EMPLOYEES = 5, ID_TYPE = 0, SALARY_TYPE = 1 } int totalHighSalaryEmployees= 0; // Start building output: printf("\nWorkers that have income greater than $5000:\t"); for(employeeID=0;employeeID<5;employeeID++){ // For each employee if(income[employeeID][1]>5000){ //check their salary totalHighSalaryEmployees++; // Increment our count of the wealthy printf("\nEmployee ID:%d Salary: $%d", employeeInfo[employeeID][0], employeeInfo[employeeID][1]); } } //Done -- // Now print number of high salary employees printf("\nNumber of Workers that have income greater than $5000:%d", totalHighSalaryEmployees); return totalHighSalaryEmployees; } 函数。

  4. 更大的()函数应该起作用 - 但值得一提的是编写if语句并不是必需的。你可以在for循环中进行检查,并从那里使用printf(),类似于在sum()函数中重新格式化代码的方式。

    此外,big()函数的结尾是 程序的结尾。逻辑流程驻留在main()的主体中。当main()结束(返回)时,程序结束。

    import pygame
    import random
    white = (255,255,255)
    black = (0,0,0)
    red = (255,0,0)
    Green= (0,225,0)
    
    pygame.init()
    windowSurface=pygame.display.set_mode((1000,1000))
    pygame.display.set_caption("1st PyGame")
    clock = pygame.time.Clock();
    counter, text = 60, '60'.rjust(3)
    pygame.time.set_timer(pygame.USEREVENT, 1000)
    font = pygame.font.SysFont('Consolas', 30)
    
    
    exit = False
    xcord=250
    ycord=250
    xchange=0
    ychange=0
    xCord=750
    yCord=750
    xChange=0
    yChange=0
    while not exit:
        windowSurface.fill((255,0,0))
        text='Cat And Mouse !!!White=Cat(arrow-keys) Black=Mouse(wasd)!!! White Wins By Catching Black But If Black Lasts A Minute Then Black Wins!!!'
        windowSurface.blit(font.render(text, True, (0, 255, 0)), (500, 500))
        pygame.display.flip()
        time.sleep(15)
        text='Get Ready Game Starts In 15 Seconds'
        windowSurface.blit(font.render(text, True, (0, 255, 0)), (500, 500))
        clock.tick(60)
        time.sleep(15)
        start_ticks=pygame.time.get_ticks()
        seconds=(pygame.time.get_ticks()-start_ticks)/1000
        for event in pygame.event.get():
            if event.type==pygame.QUIT:
                exit=True
            if event.type==pygame.KEYDOWN:
                if event.key==pygame.K_LEFT:
                    xChange-=10
                    yChange+=0
            elif event.type==pygame.KEYUP:
                if event.key==pygame.K_LEFT:
                    xChange=0
                    yChange=0
            if event.type==pygame.KEYDOWN:
                if event.key==pygame.K_RIGHT:
                    xChange+=10
                    yChange+=0
            elif event.type==pygame.KEYUP:
                if event.key==pygame.K_RIGHT:
                    xChange=0
                    yChange=0
            if event.type==pygame.KEYDOWN:
                if event.key==pygame.K_UP:
                    xChange+=0
                    yChange-=10
            elif event.type==pygame.KEYUP:
                if event.key==pygame.K_UP:
                    xChange=0
                    yChange=0
            if event.type==pygame.KEYDOWN:
                if event.key==pygame.K_DOWN:
                    xChange+=0
                    yChange+=10
            elif event.type==pygame.KEYUP:
                if event.key==pygame.K_DOWN:
                    xChange=0
                    yChange=0
            if event.type==pygame.KEYDOWN:
                if event.key==pygame.K_a:
                    xchange-=10
                    ychange+=0
            elif event.type==pygame.KEYUP:
                if event.key==pygame.K_a:
                    xchange=0
                    ychange=0
            if event.type==pygame.KEYDOWN:
                if event.key==pygame.K_d:
                    xchange+=10
                    ychange+=0
            elif event.type==pygame.KEYUP:
                if event.key==pygame.K_d:
                    xchange=0
                    ychange=0
            if event.type==pygame.KEYDOWN:
                if event.key==pygame.K_w:
                    xchange+=0
                    ychange-=10
            elif event.type==pygame.KEYUP:
                if event.key==pygame.K_w:
                    xchange=0
                    ychange=0
            if event.type==pygame.KEYDOWN:
                if event.key==pygame.K_s:
                    xchange+=0
                    ychange+=10
            elif event.type==pygame.KEYUP:
                if event.key==pygame.K_s:
                    xchange=0
                    ychange=0
        crashxCord1=xCord+10
        crashxCord2=xCord-10
        crashyCord1=yCord+10
        crashyCord2=yCord-10
    
    
        for e in pygame.event.get():
            if e.type==pygame.USEREVENT: 
                counter-=1
                text=str(counter).rjust(3) if counter > 0 else 'Black Wins'
            if e.type==pygame.QUIT: break
        else:
            if text=='Black Wins':
                windowSurface.fill(0,0,0)
                screen.blit(font.render(text, True, (0, 255, 0)), (500, 100))
                pygame.display.flip()
                clock.tick(60)
                time.sleep(10)
                exit=True
            else:
                screen.blit(font.render(text, True, (0, 255, 0)), (500, 100))
                pygame.display.flip()
                clock.tick(60)
    
    
        if crashxCord1<=xcord and crashxCord2>=xcord and crashyCord1<=ycord and crashyCord2>=ycord:
            text='White Wins'
            windowSurface.fill(255,255,255)
            screen.blit(font.render(text, True, (0, 255, 0)), (500, 100))
            pygame.display.flip()
            clock.tick(60)
            time.sleep(10)
            exit=True
        pygame.display.update()
        xcord+=xchange
        ycord+=ychange
        xCord+=xChange
        yCord+=yChange
        windowSurface.fill(red)
        pygame.draw.rect(windowSurface, black, ([xcord,ycord,20,20]))
        pygame.draw.rect(windowSurface, white, ([xCord,yCord,20,20]))
        clock.tick(60)
        pygame.display.update()