C 程序 - 输出显示在下一行而不使用换行符

C Program - Output is shown at next line without using newline character

在这段代码中,当被询问时,在键入所有用户输入后,代码必须给出相同的输出。

这是下面给出的代码的一部分,它打印输出但是在打印 city_1[i].city 的输出之后,进一步的输出打印在换行符上。

printf语句中我没有在"%s"之后使用"\n"

for (i = 0; i <= k - 1; i++) {
    printf("   %s      %d      %f%", city_1[i].city, city_1[i].p, city_1[i].l);
    //printf("\n");
}   

我正在使用 Visual Studio 2015 来调试我的代码。

谁能帮我解释一下这个问题?

下面是我的代码:

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

//GLOBAL-VARIABLE DECLARTION
#define MAX 1000

//GLOBAL-STRUCTURES DECLARATION
struct census {
    char city[MAX];
    long int p;
    float l;
};

//GLOBAL-STRUCTURE-VARIABLE DECLARATION
struct census cen[MAX] = { 0 };

//USER-DEFINED FUNCTION
struct census sortm_city(struct census city_1[]);
struct census sortm_population(struct census popu[]);
struct census sortm_literacy(struct census lite[]);
void header();

void header() {
    printf("*-*-*-*-*CENSUS_INFO*-*-*-*-*");
    printf("\n\n");
}

//PROGRAM STARTS HERE
main() {    
    //VARIABLE-DECLARATION
    int i = 0, j = 0, n = 0;
    char line[MAX] = { 0 };
    char o = { 0 };

    //FUNCTION CALL-OUT
    header();

    printf("Enter No. of City : ");
    fgets(line, sizeof(line), stdin);
    sscanf_s(line, "%d", &j);

    printf("\n\n");

    printf("Enter Name of City, Population and Literacy level");
    printf("\n\n");

    for (i = 0; i <= j - 1; i++) {
        printf("City No. %d - Info :", i + 1);
        printf("\n\n");

        printf("City Name : ");
        fgets(cen[i].city, MAX, stdin);
        printf("\n");

        printf("Population : ");
        fgets(line, sizeof(line), stdin);
        sscanf_s(line, "%d", &cen[i].p);
        printf("\n");

        printf("Literacy : ");
        fgets(line, sizeof(line), stdin);
        sscanf_s(line, "%f", &cen[i].l);
        printf("\n");

        printf("_____________________________________");
        printf("\n\n");
    }

    printf("*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* ");
    printf("Census Information");
    printf(" *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*");
    printf("\n\n");

    for (i = 0; i <= j - 1; i++) {
        printf("City No. %d - Info :", i + 1);
        printf("\n\n");

        printf("City Name : %s", cen[i].city);
        printf("\n");

        printf("Population : %d", cen[i].p);
        printf("\n");

        printf("Literacy : %0.2f", cen[i].l);
        printf("\n");

        printf("_____________________________________");
        printf("\n\n");
    }

    printf("Enter one option from the following : \n\n");
    printf("(a) To Sort the List Alphabetically. \n");
    printf("(b) To Sort the List based on Literacy Level. \n");
    printf("(c) To Sort the List based on Population. \n\n");
    printf("Please type a proper option. \n");

    n = 0;

    while (n == 0) {
        scanf_s(" %c", &o);

        switch (o) {
          case 'a':
            sortm_city(cen, j);
            n = 1;
            break;

          case 'b':
            sortm_population(cen);
            n = 1;
            break;

          case 'c':
            sortm_literacy(cen);
            n = 1;
            break;

          default:
            printf("Option INVALID \n");
            printf("Please type a proper option. \n");
            n = 0;
            break;
        }
    }

    //TERMINAL-PAUSE
    system("pause");
}

struct census sortm_city(struct census city_1[], int k) {
    int i = 0, j = 0;
    //FOR TRANSFERRING
    float b = 0;
    int s = 0;
    char line_0[MAX] = { 0 };

    for (i = 1; i <= k - 1; i++) {
        for (j = 1; j <= k - 1; j++) {
            if (strcmp(city_1[j - 1].city, city_1[j].city) > 0) {
                //SORTING THE LIST ALPHABETICALLY.
                strcpy(line_0, city_1[j - 1].city);
                strcpy(city_1[j - 1].city, city_1[j].city);
                strcpy(city_1[j].city, line_0);

                //COPYING POPULATION AND LITERACY TO RIGHT PLACE.

                //POPULATION :
                s = city_1[j - 1].p;
                city_1[j - 1].p = city_1[j].p;
                city_1[j].p = s;

                //LITERACY : 
                b = city_1[j - 1].l;
                city_1[j - 1].l = city_1[j].l;
                city_1[j].l = b;
            }
        }
    }

    printf("*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* ");
    printf("Sorted list in Alphabetical Order");
    printf(" *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*");
    printf("\n\n");

    printf("___________________________________________________\n");
    printf("|   *City Name*   |   Population   |   Literacy   | \n");

    for (i = 0; i <= k - 1; i++) {
        printf("   %s      %d      %f%", city_1[i].city, city_1[i].p, city_1[i].l);
        //printf("\n");
    }
}

struct census sortm_population(struct census popu[]) {
    printf("-------");
}

struct census sortm_literacy(struct census lite[]) {
    printf("-------");
}

fgets 包括用户在返回的字符串中键入的 \n 字符。因此,当您打印该字符串时,您会得到一个新行。

问题来自于 fgets() 在它从流中读取的行末尾留下的换行符。如果缓冲区太短或者文件中的最后一行没有以行结束符结尾,缓冲区将不会在最后的 [=15=] 之前以 \n 结束,在所有其他情况下,它将.

删除换行符的简单方法是:

line[strcspn(line, "\n")] = '[=10=]';

如果找到一个,它会覆盖 \n,否则会用 [=15=].

覆盖 [=15=]

请注意,您应该测试 fgets() 的 return 值,它 returns NULL 如果它无法读取文件末尾的一行。

另请注意,以这种方式编写 for 循环更简单、更惯用:

for (i = 0; i < j; i++) { ... }

将包含索引 0 而不会包含索引 j,这与您的语法相同,但使用更简单、更具可读性的方式。

您还可以使用 qsort 通过 3 种不同的比较函数对 table 进行排序。

另请注意,您对 main() 的定义对于 C99 和更高版本的 C 标准而言已过时且不正确。你应该写 int main(void)int main(int argc, char *argv[]).

以下是问题列表:

  • 您将人口普查成员 p 定义为 long int 但使用 %d 通过 sscanf 读取它并使用 printf 打印它,正确的格式是%ld.
  • 你把sortm_xxx函数定义为return一个struct census,这是不正确的,sortm_city确实return没什么,它们应该是定义为 void.
  • header 应声明并定义为 void header(void)
  • main 应定义为 int main(void)
  • 您使用 scanf_ssscanf_s。这些功能可能是 Visual Studio 推荐的,但它们在其他系统上并不总是可用,scanfsscanf 是并且可以安全地使用一些预防措施,特别是对于 %s%[ 格式,无论如何您都不会在此处使用。
  • fgets 在行尾留下 \n。您应该检查 retuen 值以检测文件过早结束并删除 \n。我定义了一个效用函数 xgets() 来完成这两项工作。 strcspn() returns 其字符串参数中不在作为第二个字符串参数给出的列表中的字符数。
  • 打印代码使用%f为识字级别,结果小数点后6位(默认),应使用%7.2f获取小数点后2位并对齐列内容。
  • 您必须使用 %% 打印 % 字符 printf
  • 我在你的 printf 格式字符串中添加了一些对齐参数来对齐输出,假设是固定宽度的字体:"| %-15s | %10ld | %7.2f%% |"%-15s 在城市名称后用空格将城市名称填充到 15 个字符,%10ld 在人口数字 之前用空格将人口填充到 10 个字符。 %7.2f 生成 2 位小数并在识字数字前用空格填充 ..
  • 前最多 7 个字符
  • 我使用 qsort 并为 3 个排序选项定义了 3 个比较函数。
  • 我将打印人口普查数据的代码移到了一个单独的函数中。最好以这种方式分解代码以编写更少的代码并避免以后修复错误时出现不一致。

这里是更正和简化的版本:

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

//GLOBAL-VARIABLE DECLARTION
#define MAX 1000

//GLOBAL-STRUCTURES DECLARATION
struct census {
    char city[MAX];
    long int p;
    float l;
};

//GLOBAL-STRUCTURE-VARIABLE DECLARATION
struct census cen[MAX] = { 0 };

//USER-DEFINED FUNCTION
void header(void);
void sortm_city(struct census cp[], int n);
void sortm_population(struct census cp[], int n);
void sortm_literacy(struct census cp[], int n);
void print_census(struct census cp[], int k, const char *legend);

void header(void) {
    printf("*-*-*-*-*CENSUS_INFO*-*-*-*-*");
    printf("\n\n");
}

char *xgets(char *dest, int size, FILE *fp) {
    /* read a line from the user */
    if (!fgets(dest, size, fp)) {
        /* read failed, end of file detected */
        printf("Premature end of file\n");
        exit(1);
    }
    /* strip the \n if present */
    dest[strcspn(dest, "\n")] = '[=12=]';
    return dest;
}

//PROGRAM STARTS HERE
int main(void) {
    //VARIABLE-DECLARATION
    int i = 0, j = 0, n = 0;
    char line[MAX] = { 0 };
    char o = { 0 };

    //FUNCTION CALL-OUT
    header();

    printf("Enter No. of City : ");
    xgets(line, sizeof(line), stdin);
    if (sscanf(line, "%d", &j) != 1)
        return 1;

    printf("\n\n");
    printf("Enter Name of City, Population and Literacy level");
    printf("\n\n");

    for (i = 0; i < j; i++) {
        printf("City No. %d - Info :", i + 1);
        printf("\n\n");

        printf("City Name : ");
        xgets(cen[i].city, MAX, stdin);
        printf("\n");

        printf("Population : ");
        xgets(line, sizeof(line), stdin);
        sscanf(line, "%ld", &cen[i].p);
        printf("\n");

        printf("Literacy : ");
        xgets(line, sizeof(line), stdin);
        sscanf(line, "%f", &cen[i].l);
        printf("\n");

        printf("_____________________________________");
        printf("\n\n");
    }

    printf("*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* ");
    printf("Census Information");
    printf(" *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*");
    printf("\n\n");

    for (i = 0; i < j; i++) {
        printf("City No. %d - Info :", i + 1);
        printf("\n\n");

        printf("City Name : %s", cen[i].city);
        printf("\n");

        printf("Population : %ld", cen[i].p);
        printf("\n");

        printf("Literacy : %0.2f", cen[i].l);
        printf("\n");

        printf("_____________________________________");
        printf("\n\n");
    }

    printf("Enter one option from the following : \n\n");
    printf("(a) To Sort the List Alphabetically. \n");
    printf("(b) To Sort the List based on Literacy Level. \n");
    printf("(c) To Sort the List based on Population. \n\n");
    printf("Please type a proper option. \n");

    n = 0;
    while (n == 0) {
        scanf(" %c", &o);

        switch (o) {
        case 'a':
            sortm_city(cen, j);
            n = 1;
            break;

        case 'b':
            sortm_population(cen, j);
            n = 1;
            break;

        case 'c':
            sortm_literacy(cen, j);
            n = 1;
            break;

        default:
            printf("Option INVALID \n");
            printf("Please type a proper option. \n");
            n = 0;
            break;
        }
    }

    //TERMINAL-PAUSE
    system("pause");
}

void print_census(struct census cp[], int k, const char *legend) {
    int i;

    printf("*-*-*-*-*-*-*-*- %s *-*-*-*-*-*-*-*-*-*", legend);
    printf("\n\n");
    printf("___________________________________________________\n");
    printf("|    City Name    |   Population   |   Literacy   |\n");
    printf("___________________________________________________\n");

    for (i = 0; i < k; i++) {
        printf("| %-15s |   %10ld   |   %7.2f%%   |", cp[i].city, cp[i].p, cp[i].l);
        printf("\n");
    }
    printf("___________________________________________________\n");
    printf("\n\n");
}

int compare_census_city(const void *a, const void *b) {
    const struct census *ca = a;
    const struct census *cb = b;
    return strcmp(ca->city, cb->city);
}

int compare_census_population(const void *a, const void *b) {
    const struct census *ca = a;
    const struct census *cb = b;
    if (ca->p > cb->p)
        return -1;
    if (ca->p < cb->p)
        return 1;
    return 0;
}

int compare_census_literacy(const void *a, const void *b) {
    const struct census *ca = a;
    const struct census *cb = b;
    if (ca->l > cb->l)
        return -1;
    if (ca->l < cb->l)
        return 1;
    return 0;
}

void sortm_city(struct census cp[], int n) {
    qsort(cp, n, sizeof(struct census), compare_census_city);
    print_census(cp, n, "Sorted list in Alphabetical Order");
}

void sortm_population(struct census cp[], int n) {
    qsort(cp, n, sizeof(struct census), compare_census_population);
    print_census(cp, n, "Sorted list by decreasing Popupation");
}

void sortm_literacy(struct census cp[], int n) {
    qsort(cp, n, sizeof(struct census), compare_census_literacy);
    print_census(cp, n, "Sorted list in decreasing Literacy level");
}