代码之家  ›  专栏  ›  技术社区  ›  obvionaoe

printf()在错误的位置打印换行符

  •  3
  • obvionaoe  · 技术社区  · 6 年前

    我是C语言的初学者,所以请原谅我的错误!

    我试图用printf()打印一些格式化的值,但它在输出的中间开始换行,即使没有“\n”! 问题出现在第442行的function list\u主题中。

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <sys/stat.h>
    #include <sys/types.h>
    #include <time.h>
    #include <unistd.h>
    
    typedef struct
    {
        int t_id;
        char t_name[35];
        char date_creation[30];
        char last_post_date[30];
        int sub_users;
        int num_posts;
        char t_desc[500];
    } topic;
    
    typedef struct
    {
        int u_type;
        int t_maxreach;
        int u_sub_topic[15];
        char u_name[16];
        char u_pass[16];
    } utilizador;
    
    void instalar();
    void menu_inicial();
    void menu_admin();
    void menu_topic();
    void menu_user();
    void login();
    void options();
    void topic_gest();
    void user_gest();
    void stats();
    void new_topic();
    void alt_topic();
    void rmv_topic();
    void list_topic();
    void new_user();
    void val_new_user();
    void list_user();
    void edit_user();
    void erro();
    void erro_app();
    void erro_cred();
    
    int main()
    {
        struct stat st = { 0 };
        int n;
    
        if (stat("SUP", &st) == -1)                     //verifica se o diretório já existe 
        {
            instalar();                                   //chama a função instalar()
        }
    
        menu_inicial();                                 //chama a função menu_inicial()
        scanf("%d", &n);                                //lê a opção escolhida pelo utilizador
    
        while (n != 2)
        {
            switch (n)
            {
            case 1: {login(); break; }
            default: {erro(); }
            }
    
            menu_inicial();                               //chama a função menu_inicial()
            scanf("%d", &n);                              //lê a opção escolhida pelo utilizador
    
        }
    
        system("clear");
        return 0;
    }
    
    void instalar()                                   //cria o diretório base e o administrador padrão
    {
        {
            system("clear");
            printf("O programa não está instalado. Deseja instalar? [s/n]\n");
    
            char t;                                                 //recebe input
    
            for (int s = 0; s == 0;)
            {
                scanf("%c", &t);
                getchar();
    
                if (t == 's')                                                   //se o input for 's' instala
                {
                    system("clear");
                    printf("A instalar...\n\n");
    
                    mkdir("SUP", 0700);
                    mkdir("SUP/Topicos/", 0700);
    
                    FILE *ft = fopen("SUP/Topicos/topicos.dat", "wb");
    
                    topic tbase;
    
                    tbase.t_id = 1;
    
                    strcpy(tbase.t_name, "Topico inicial");
    
                    time_t curtime;
                    time(&curtime);
                    strcpy(tbase.date_creation, ctime(&curtime));
                    strcpy(tbase.last_post_date, ctime(&curtime));
    
                    tbase.sub_users = 0;
                    tbase.num_posts = 0;
    
                    strcpy(tbase.t_desc, "topic desc");
    
                    fwrite(&tbase, sizeof(topic), 1, ft);
                    fclose(ft);
    
                    //testar
                    topic input;
                    ft = fopen("SUP/Topicos/topicos.dat", "rb");
                    while (fread(&input, sizeof(topic), 1, ft))
                    {
                        printf("id = %d \nname = %s \ntopic desc = %s \nlast post date = %s \nsubscribed users = %d \nnumber of posts = %d", input.t_id, input.t_name, input.t_desc, input.last_post_date, input.sub_users, input.num_posts);
                    }
                    getchar();
    
                    FILE *f = fopen("SUP/utilizadores.dat", "wb");
                    utilizador admin;
                    admin.u_type = 1;
                    admin.t_maxreach = 0;
                    strcpy(admin.u_name, "admin");
                    strcpy(admin.u_pass, "admin");
                    admin.u_sub_topic[0] = tbase.t_id;
                    fwrite(&admin, sizeof(utilizador), 1, f);
                    fclose(f);
    
                    printf("Pressione a tecla ENTER para continuar...");
                    getchar();
    
                    break;
                }
                else if (t == 'n')                                   //se o input for 'n' não instala e sai do programa
                {
                    system("clear");
                    exit(0);
                }
            }
        }
    }
    
    void menu_inicial()
    {
        system("clear");
    
        printf("----------** Menu de registo **----------\n");
        printf("|                                       |\n");
        printf("|        1) Login / Autenticação        |\n");
        printf("|        2) Sair                        |\n");
        printf("|                                       |\n");
        printf("-----------------------------------------\n");
    }
    
    void menu_admin()                               //menu depois do login
    {
        system("clear");
    
        printf("------------------** Menu **-------------------\n");
        printf("|                                             |\n");
        printf("|            1) Gerir Tópicos                 |\n");
        printf("|            2) Gerir Utilizadores            |\n");
        printf("|            3) Estatísticas                  |\n");
        printf("|            4) Logout                        |\n");
        printf("|                                             |\n");
        printf("-----------------------------------------------\n");
    }
    
    void menu_topic()
    {
        system("clear");
    
        printf("-------------------** Gestão de Tópicos **--------------------\n");
        printf("|                                                            |\n");
        printf("|              1) Criar novo tópico                          |\n");
        printf("|              2) Alterar atributos de um tópico             |\n");
        printf("|              3) Eliminar tópico                            |\n");
        printf("|              4) Listar tópicos                             |\n");
        printf("|              5) Voltar atrás                               |\n");
        printf("|                                                            |\n");
        printf("--------------------------------------------------------------\n");
    }
    
    void menu_user()
    {
        system("clear");
    
        printf("---------------------** Gestão de Utilizadores **--------------------\n");
        printf("|                                                                   |\n");
        printf("|                1) Criar novo utilizador                           |\n");
        printf("|                2) Validar pedido de novo utilizador               |\n");
        printf("|                3) Listar utilizadores                             |\n");
        printf("|                4) Editar utilizadores                             |\n");
        printf("|                5) Voltar atrás                                    |\n");
        printf("|                                                                   |\n");
        printf("---------------------------------------------------------------------\n");
    }
    
    void login()                                                                     //processo de autenticação do utilizador
    {
        system("clear");
    
        char name[16], *pass;
        int res;
    
        utilizador input;
    
        printf("----------** Login / Autenticação **----------\n");
    
        printf("Nome de utilizador: ");
        scanf("%s", name);
        getchar();
    
        pass = getpass("Palavra-passe: ");
    
        FILE *f = fopen("SUP/utilizadores.dat", "rb");
    
        while (fread(&input, sizeof(utilizador), 1, f))                                  //testa se as credenciais são válidas e são de administrador
        {
            if (input.u_type == 1)
            {
                res = strcmp(name, input.u_name);
                res += strcmp(pass, input.u_pass);
    
                if (res == 0)
                {
                    break;
                }
            }
            else if (input.u_type == 0)
            {
                res = strcmp(name, input.u_name);
                res += strcmp(pass, input.u_pass);
    
                if (res == 0)
                {
                    res = 2;
                    break;
                }
            }
        }
    
        fclose(f);
    
        switch (res)
        {
        case 0: {options(); break; }
        case 2: {erro_app(); break; }
        default: {erro_cred(); }
        }
    }
    
    void options()                                                    //escolha de opções depois do login
    {
        int i;
    
        menu_admin();
    
        scanf("%d", &i);
        getchar();
    
        while (i != 4)
        {
            switch (i)
            {
            case 1: {topic_gest(); break; }
            case 2: {user_gest(); break; }
            case 3: {stats(); break; }
            default: {erro(); }
            }
    
            menu_admin();
            scanf("%d", &i);
            getchar();
        }
    }
    
    void topic_gest()                                                          //escolher opções de gestão de tópicos
    {
        int i;
    
        menu_topic();
        scanf("%d", &i);
        getchar();
    
        while (i != 5)
        {
            switch (i)
            {
            case 1: {new_topic(); break; }
            case 2: {alt_topic(); break; }
            case 3: {rmv_topic(); break; }
            case 4: {list_topic(); break; }
            default: {erro(); }
            }
    
            menu_topic();
            scanf("%d", &i);
            getchar();
        }
    }
    
    void user_gest()                                                           //escolher opções de gestão de utilizadores
    {
        int i;
    
        menu_user();
        scanf("%d", &i);
        getchar();
    
        while (i != 5)
        {
            switch (i)
            {
            case 1: {new_user(); break; }
            case 2: {val_new_user(); break; }
            case 3: {list_user(); break; }
            case 4: {edit_user(); break; }
            default: {erro(); }
            }
    
            menu_user();
            scanf("%d", &i);
            getchar();
        }
    }
    
    void stats()                                                               //mostra as estatísticas dos tópicos e dos utilizadores
    {
    
    }
    
    void new_topic()                                                           //cria um tópico novo
    {
        system("clear");
    
        topic new, filein;
    
        FILE *f = fopen("SUP/Topicos/topicos.dat", "ab+");
    
        printf("---------------------** Criar Novo Tópico **--------------------\n\n");
        printf("Nome do tópico <máximo de 50 carateres>: ");
        fgets(new.t_name, 35, stdin);
    
        strcpy(new.t_name, strtok(new.t_name, "\n"));
    
        if (strlen(new.t_name) > 30)                                                                                      //testa se o nome inserido é demasiado comprido
        {
            system("clear");
    
            printf("O nome é demasiado comprido, por favor insira outro nome!\n\n");
            printf("Pressione a tecla ENTER para voltar atrás...");
            getchar();
    
            return;
        }
        else
        {
            while (fread(&filein, sizeof(topic), 1, f))
            {
                if (strcmp(filein.t_name, new.t_name) == 0)                                                                   //testa se o tópico inserido já existe
                {
                    system("clear");
    
                    printf("Este tópico já existe, por favor insira outro nome!\n\n");
                    printf("Pressione a tecla ENTER para voltar atrás...");
                    getchar();
    
                    return;
                }
            }
        }
    
        rewind(f);
    
        new.t_id = 1;
    
        while (fread(&filein, sizeof(topic), 1, f))                                                                       //testa a id dos tópicos já registados para não terem ids duplicados
        {
            if (new.t_id <= filein.t_id)
            {
                new.t_id += 1;
                printf("id = %d", new.t_id);
                getchar();
            }
        }
    
        printf("Descrição do tópico <máximo de 500 carateres>: ");
        fgets(new.t_desc, 500, stdin);
    
        time_t curtime;
    
        time(&curtime);
    
        strcpy(new.date_creation, ctime(&curtime));
        strcpy(new.last_post_date, ctime(&curtime));
    
        new.sub_users = 0;
        new.num_posts = 0;
    
        fwrite(&new, sizeof(topic), 1, f);
        fclose(f);
    
        printf("Tópico '%s' criado com sucesso!\n\n", new.t_name);
        printf("Pressione a tecla ENTER para continuar...");
        getchar();
    
    }
    
    void alt_topic()
    {
        system("clear");
    
        char name[30];
    
        printf("-------------------------** Alterar Tópico **------------------------\n\n");
        printf("Insira o nome do tópico que deseja alterar: ");
        fgets(name, 30, stdin);
    
        printf("name = %s", name);
        getchar();
    }
    
    void rmv_topic()
    {
    
    }
    
    void list_topic()
    {
        system("clear");
    
        printf("--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\n");
        printf("| ID   | Nome                           | Descrição                                    | Criado em                     | Último post em                | Utilizadores subscritos | Nº de posts   |\n");
        printf("--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\n");
    
        FILE *ft = fopen("SUP/Topicos/topicos.dat", "rb");
        topic input;
        while (fread(&input, sizeof(topic), 1, ft))
        {
            printf("| %04d | %-30s | %-44s | %-25s | %-29s | %-23d | %-13d |\n", input.t_id, input.t_name, input.t_desc, input.date_creation, input.last_post_date, input.sub_users, input.num_posts);
            printf("--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\n");
        }
        getchar();
    }
    
    void new_user()
    {
    
    }
    
    void val_new_user()
    {
    
    }
    
    void list_user()
    {
    
    }
    
    void edit_user()
    {
    
    }
    
    void erro()                                                                  //dá mensagem de erro na escolha da opção
    {
        system("clear");
    
        printf("Opção desconhecida!\n\n");
        printf("Pressione a tecla ENTER para continuar...");
        getchar();
    }
    
    void erro_app()                                                            //dá mensagem de credenciais sem autorização e sai do programa
    {
        system("clear");
    
        printf("As credenciais inseridas não são credenciais de administrador!\n");
        printf("Por favor use o programa CLIENTE para iniciar a sessão!\n\n");
        printf("Pressione a tecla ENTER para sair...");
        getchar();
    
        system("clear");
        exit(0);
    }
    
    void erro_cred()                                                          //dá mensagem de credenciais erradas e reinicia login()
    {
        system("clear");
    
        printf("Nome de utilizador e/ou palavra-passe incorretos!\n\n");
        printf("Pressione a tecla ENTER para continuar...");
        getchar();
        getchar();
    
        login();
    }
    

    输出应如下所示:

    --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    | ID   | Nome                           | Descrição                                    | Criado em                     | Último post em                | Utilizadores subscritos | Nº de posts   |
    --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    | 0001 | Topico inicial                 | topic desc                                   | Tue May 15 12:36:03 2018      | Tue May 15 12:36:03 2018      | 0                       | 0             |
    --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    

    但结果是这样的:

    --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    | ID   | Nome                           | Descrição                                    | Criado em                     | Último post em                | Utilizadores subscritos | Nº de posts   |
    --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    | 0001 | Topico inicial                 | topic desc                                   | Tue May 15 12:36:03 2018
     | Tue May 15 12:36:03 2018
         | 0                       | 0             |
    --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    

    我不知道会出什么问题!

    1 回复  |  直到 6 年前
        1
  •  10
  •   Community CDub    4 年前

    你的程序的问题是 ctime 返回带有 '\n' 在最后。您可以看到,伪新行总是在打印时间之后出现。

    您可以在将其复制到指定缓冲区后将其删除。

    例如,之后

    strcpy(new.date_creation, ctime(&curtime));
    

    您可以添加

    new.date_creation[strlen(new.date_creation)-1] = '\0';
    

    您需要将其添加到创建的每个字符串中 ctime公司 (或 asctime ,如果您以后使用)。

    实际上,这个的存在 “\n” 由C标准保证。您可以查看以下部分: ctime asctime

    引用 C11 §7.27.3.1p2

    这个 asctime公司 函数转换指向的结构中的故障时间 timeptr 转换为表单中的字符串

    Sun Sep 16 01:03:52 1973\n\0