【问题标题】:How to resort an array with file input?如何使用文件输入对数组进行排序?
【发布时间】:2017-07-25 01:16:55
【问题描述】:

我正在编写一个程序,它会询问用户一个“n”值,然后他们将输入“n”个值,这些值将存储到一个数组中并进行排序。我已经很容易完成了这部分。 我将把这个数组与从文本文件中读取的数字的输入进行比较。如果数字大于任何当前数组值,它将替换它们并将其余部分向下滑动。这将创建一个包含最大 'n' 值的数组

示例: n = 4 n 值为:999 972 954 462 937

a[4] = {999, 972, 954, 462, 937};

排序:

a[4] = {999, 972, 954, 937, 462};

如果文件输入是 968,结果是。 表示:

a[4] = {999, 972, 968, 937, 937};

这是我当前的代码。

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

int main(int argc, char *argv[]){
    if (argc<3)                            //error checking
        return -1;
    int size = atoi(argv[2]);
    int a[size];
    int i, j, temp=0;
    printf("Enter %d numbers\n", size);     //user array input for size and n values
    for(i = 0; i < size; i++)
        scanf("%d", &a[i]);
    for(i=0; i < size; i++){                //sorting array
        for(j = i+1; j <size; j++){
            if( a[i] < a[j]){
                temp = a[i];
                a[i] = a[j];
                a[j] = temp; 
            }
        }
    }
    FILE *input;
    input = fopen(argv[1], "r");
    if(input ==NULL)                          //error checking
        return -1;
    if(fscanf(input, "%d", &temp) != 1)
        return -1;
    while(fscanf(input, "%d", &temp) ==1){   //loop while  there is file input
        for(i =1 < size; i++){                //check if temp is larger than array values
            if(temp > a[i] && temp < a[i-1]){      
                for(j = size-1; j >= i; j--)   //slide down the rest of the array
                    a[j] = a[j-1];
                a[i] = temp;
            }
        }
    }
    for(i=0; i <size; i++){                    //print out array
        printf("%d ", a[i]);
    }
    return (0);
}

如果我已经创建了数组和值,而不是使用用户输入,我已经尝试过这个更小更简单的技能。我还只是通过一个增加数字值而不是从文件中读取的循环传递了数组检查序列。这似乎适用于

a[5] = {10, 8, 6, 4, 2};
number = 5;   // number++  number = 6 number = 7... until 10
result: a[5] = {10, 9, 8, 7, 6};

我很遗憾地说,即使程序在开始时没有打印正确的数组,我也可以看到文件中有数字。循环仍在通过文件,但在某一时刻,输出刚刚开始成为已排序的用户数组。我似乎无法正确获取数组值。有什么想法吗?

【问题讨论】:

  • 5 个元素,而 n = 4?奇怪的问题集。
  • if(fscnf(input, "%d", %temp) != 1) 行会因为% 的误用而产生编译错误。另请注意,标准库没有fscnf()(不是fscanf())函数。
  • 另一个编译错误将在for(i =1 &lt; size; i++){ 行中发出,因为分号的数量少于预期。
  • @MikeCAT,抱歉打错了。我在 vdi 上有我的实际程序。我无法复制和粘贴我的代码。
  • 请不要在此处重新输入您的代码以发布 - 这会导致问题。了解如何复制'n'粘贴您的代码,以免引入令人分心的错误。我们不能说它们是转录错误(并且不必担心它们)。请注意,如果您粘贴代码并且它没有缩进,则在编辑框中选择代码并使用其上方的 {} 将所选材料缩进为代码。

标签: c arrays file sorting user-input


【解决方案1】:

从我昨天的 cmets 开始,如果错误是由于重新输入您的代码造成的,我深表歉意,但这就是您想要尝试按照 Jonathan 指示进行剪切和粘贴的全部原因 - 消除转录过程中的人为错误。

我想我了解您的主要问题是什么。如果您的目标是从stdin 读取一些用户输入值,按降序对它们进行排序,然后打开文件并按排序顺序将单个附加值读入数组,那么您必须为最终声明时数组中的值(如果使用 VLA)。否则,您要么需要创建第二个足够大的 VLA 来存储来自使用和文件的值,然后将用户提供的值复制到新数组,要么最初动态分配数组(使用 malloccalloc)和然后 realloc 根据需要为其他值添加空间。

在这种情况下,这并不难,因为您知道您正在从文件中读取一个值。只需从命令行参数中读取size,然后将您的数组创建为int a[size + 1];

您可以通过多种方式处理其余的任务。在您读取(并验证)用户输入后,您可以按降序对您的值进行排序,从文件中读取值,并创建一个 insert & shuffle 例程来插入以正确顺序的值并将剩余的数组元素向下移动,(可能是一种不太容易出错的方法)只是将文件中的元素添加到数组的末尾,然后调用你的 @ 987654327@再次套路。

(注意:你应该习惯使用qsort,而不是尝试重新发明冒泡排序等。它的效率要高几个数量级,而且更不容易出错)

您需要限制(或消除)您对atoi 的使用,因为它提供零错误检查。更好的方法是使用strtol,然后检查errno,并对照原件检查end-pointer,以确定是否读取了任何数字。下面是一个简单的辅助函数,包含对 strtol 的错误检查,以确保您拥有 size 的实际值。

此外,要小心。虽然您可能期望用户会输入 size 整数值,但不能保证他们会输入。最好跟踪实际输入的值的数量,并在数组的后续迭代中使用该值,而不是在代码的其余部分中盲目地迭代 for (i = 0; i &lt; size; i++)

您是尝试从文件中读取的值的就地插入,还是只是将其添加到数组的末尾并再次调用您的排序例程,这取决于您。我鼓励您将排序代码移动到一个函数中以提供这种灵活性,而不必复制 main 中的代码。查看以下内容,如果您有任何问题,请告诉我。由于我认为这是一个家庭作业,因此就地插入的情况如下所示(但简单地将文件值添加到末尾并再次调用排序代码被注释掉了)

#include <stdio.h>
#include <stdlib.h> /* for strtol       */
#include <limits.h> /* for LONG_MAX/MIN */
#include <errno.h>  /* for ERANGE,errno */

void sort_int_array_dec (int *a, size_t size);
long xstrtol (char *p, char **ep, int base);

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

    /* read size as first argument, or 5 if none given */
    int size = argc > 2 ? (int)xstrtol (argv[2], NULL, 10) : 5,
        a[size + 1],    /* variable length array for user + file values */
        n = 0,          /* number of values from user */
        fval,           /* value read from file */
        temp,           /* temporary value for array */
        i = 0;
    FILE *fp = NULL;

    if (size < 1) return 1;

    printf ("enter %d integers\n", size);

    while (n < size) { /* read up to size values */

        int result, c;

        printf ("  integer[%2d] : ", n + 1);

        /* validate read of each value using scanf return */
        if ((result = scanf ("%d", &temp)) != 1) {

            if (result == EOF) { /* always check for EOF */
                fprintf (stderr, "user canceled input.\n");
                break;
            }

            fprintf (stderr, "error: invalid conversion.\n");

            /* empty input buffer of invalid entry */
            while ((c = getchar()) != '\n' && c != EOF) {}
        }
        else    /* good value read, save, increment n */
            a[n++] = temp;
    }

    sort_int_array_dec (a, n); /* sort a */

    printf ("\nsorted array before inserting value from file:\n\n");
    for (int i = 0; i < n; i++)
        printf ("a[%2d]: %d\n", i, a[i]);

    if (!(fp = fopen (argv[1], "r"))) {
        fprintf (stderr, "error: file open failed '%s'\n", argv[1]);
        return 1;
    }

    if (fscanf (fp, "%d", &fval) != 1) {  /* read value from file */
        fprintf (stderr, "error: read of file value failed.\n");
        return 1;
    }
    printf ("\n value from file: %d\n\n", fval);


    /* add fval into array in descending sort order 
     * (you can add it anywhere and simply call sort again, e.g.)
     */
//     a[n] = fval;    /* add it to the end of the array */
//     sort_int_array_dec (a, n + 1);    /* sort a again */

    for (i = 1; i < n + 1; i++) {
        if (fval > a[i-1]) {
            temp = a[i-1];
            a[i-1] = fval;
            break;      /* temp now holds value to insert at i */
        }
    }

    if (i == n + 1)     /* if already at last element just set it */
        a[n] = fval;
    else    /* otherwise, insert and shuffle remaining elements down */
        for (int j = i; j < n + 1; j++) {
            int mov = a[j];
            a[j] = temp;
            temp = mov;
        }

    printf ("sorted array after inserting value from file:\n\n");
    for (int i = 0; i < n + 1; i++)
        printf (" a[%2d]: %d\n", i, a[i]);

    return 0;
}

/** sort integer array descending (your code) */
void sort_int_array_dec (int *a, size_t size)
{
    size_t i, j;
    int temp;

    if (size < 2) return;   /* nothing to sort */

    for (i = 0; i < size; i++) {
        for (j = i + 1; j < size; j++) {
            if (a[i] < a[j]) {
                temp = a[i];
                a[i] = a[j];
                a[j] = temp; 
            }
        }
    }
}

/** a simple strtol implementation with error checking.
 *  any failed conversion will cause program exit. Adjust
 *  response to failed conversion as required.
 */
long xstrtol (char *p, char **ep, int base)
{
    errno = 0;

    char *endpt = ep ? *ep : NULL;

    long tmp = strtol (p, &endpt, base);

    /* Check for various possible errors */
    if ((errno == ERANGE && (tmp == LONG_MIN || tmp == LONG_MAX)) ||
        (errno != 0 && tmp == 0)) {
        perror ("strtol");
        exit (EXIT_FAILURE);
    }

    if (endpt == p) {
        fprintf (stderr, "No digits were found\n");
        exit (EXIT_FAILURE);
    }

    if (ep) *ep = endpt;

    return tmp;
}

使用/输出示例

$ cat dat/file.txt
523

$ ./bin/addintoarray dat/file.txt 4
enter 4 integers
  integer[ 1] : 400
  integer[ 2] : 500
  integer[ 3] : 600
  integer[ 4] : 700

sorted array before inserting value from file:

a[ 0]: 700
a[ 1]: 600
a[ 2]: 500
a[ 3]: 400

 value from file: 523

sorted array after inserting value from file:

 a[ 0]: 700
 a[ 1]: 600
 a[ 2]: 523
 a[ 3]: 500
 a[ 4]: 400

【讨论】:

    【解决方案2】:
    /*I'm a beginner C programmer so I don't know much of the syntax.
      But I think I can help you with that problem.
    
      I created a simple code and I hope I can really help
    
      the integers from the file must be already sorted.
      So the only integer that we will sort is the recent integer that the user inputed.
      */
    
    
      /*So here's my code of sorting array of integers coming from file.
       Please give it a try.
        It's not the same syntax as your code but I know you can see my point*/
    
    #include <stdio.h>
    #include <stdlib.h>
    
    //my style here is I'm declaring the max Num that I want to put in array. 
    //But you can do this with different style.
    
    #define MAX_ARRAY 10
    
    //I created separate functions
    void readFile(int num_arr[]);
    void sortArray(int num_arr[]);
    void writeFile(int num_arr[]);
    
    int main()
    {
        int num_arr[MAX_ARRAY + 1]; // take note that I added 1 (one). And you will see later why I did that
    
    
        readFile(num_arr);
    
        sortArray(num_arr);
    
        writeFile(num_arr);
    
        //Now we can sort them. Use a temp_num holder.
    
        return 0;
    }
    
    void readFile(int num_arr[])
    {
        int x = 0;
        int y = 0;
        int temp_num;
    
        FILE *sample_file_pointer = fopen("sample_file.txt", "r");
    
        //first I read the integers from the file and put them in int array.
        while(fscanf(sample_file_pointer, " %d\n", &num_arr[x]) == 1)
        {
            x++;
        }//after reading the integers, the last element of the array we declared is still unused.. Now we will use it.
        fclose(sample_file_pointer);
    
        //now we will use the unused element by entering the 'n'. Then we will sort the array later.
        printf("Enter value of n: ");
        scanf(" %d", &num_arr[MAX_ARRAY]);//We put the n value in the last element of the array
    }
    
    void sortArray(int num_arr[])
    {
        int x = MAX_ARRAY;//We will use this to point the last element of the array.
        int temp_num;
    
        /*because the array from
        the file is already
        sorted, (I know you can
        do the sorting of that.
        That's why I didn't include
        it here to make this short)
        we can just test the most recent
        integer that is added by the user*/
    
        //We do that with this loop
        for(int i = MAX_ARRAY; i > 0; i--)
        {
            if(num_arr[x] >= num_arr[i - 1])
            {
                temp_num = num_arr[x];
                num_arr[x] = num_arr[i - 1];
                num_arr[i - 1] = temp_num;
    
                //now set the x to the swapped element to follow the recent number all through. Till the element test becomes 1.
                x = i - 1;
            }
        }
    
        //now we're ready to write this sorted array to a file again
    }
    
    void writeFile(int num_arr[])
    {
        FILE *sample_file_pointer = fopen("sample_file.txt", "w");
    
        for(int i = 0; i < MAX_ARRAY; i++)
        {
            fprintf(sample_file_pointer, "%d\n", num_arr[i]);
        }
        //We can ignore the last element of the array. She's out of the group now. It's her fault for being the lowest.. LOL..
    
        fclose(sample_file_pointer);
    }
    

    【讨论】:

    • 您可以将这些函数组合到您的代码中。它可以解决您的问题。如果您将它们与某些东西进行比较,也不要忘记将您的数组设置为 {NULL}。将它们与某个变量进行比较而不初始化它们会导致错误。 (根据我的经验)
    猜你喜欢
    • 1970-01-01
    • 2016-05-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-22
    • 1970-01-01
    • 2014-11-05
    相关资源
    最近更新 更多