我在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 | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------我不知道什么可能是错的!
I'm somewhat of a beginner in C so please excuse any crass mistakes!
I'm trying to print some formatted values with printf() but it starts a newline in the middle of the output even though there isn't a '\n'! The problem is in function list_topic on line 442.
#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(); }The output should be like this:
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | 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 | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------But ends up like this:
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | 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 | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------I have no clue what could be wrong!
最满意答案
你的程序的问题是, 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
The issue with your program is that ctime returns the time string with a '\n' at the end. You can see that the spurious new lines are always after printing the time.
You can remove that after copying it to the designated buffer.
For example after
strcpy(new.date_creation, ctime(&curtime));You can add
new.date_creation[strlen(new.date_creation)-1] = '\0';You need to add this to every string you are creating from ctime (or asctime, if you use that in future).
Actually, the existence of this '\n' is guaranteed by the C standard. You can look at the sections for ctime and asctime.
Quoting C11, chapter §7.27.3.1p2
The asctime function converts the broken-down time in the structure pointed to by timeptr into a string in the form
Sun Sep 16 01:03:52 1973\n\0
更多推荐
发布评论