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

时间:2018-05-15 12:24:35

标签: c printf

我有点像C的初学者,所以请原谅任何粗心的错误!

我正在尝试使用printf()打印一些格式化值,但即使没有'\ n',它也会在输出中间开始换行! 问题出在第442行的list_topic函数中。

#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 个答案:

答案 0 :(得分:10)

您的计划存在的问题是,ctime会在结尾处返回时间字符串,其中包含'\n'。你可以看到假的新行总是在打印时间之后。

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

例如在

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

您可以添加

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

您需要将此内容添加到您要创建的每个字符串ctime(或asctime,如果您将来再使用它)。

实际上,这个'\n'的存在是由C标准保证的。您可以查看ctimeasctime的各个部分。

引用C11,章§7.27.3.1p2

  

asctime函数将timeptr指向的结构中的细分时间转换为

形式的字符串      

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