Strtok is returning (null) after the first token - c

I'm trying to separate a string read from a file by the token '#'. StrTok separates the first token correctly but when i print what is supposed to be the second token it returns nothing but (null).
I tried to change the format of the file that is being read and using an aux variable to hold the content of strtok(NULL,"#"), but the results dont change.
void ler_fich_cidades(Lista_Cidades cidade,Lista_Pontos pt){
FILE *p;
int file_check=0;
char linha[TAM];
Lista_Pontos ptos;
Cada_cidade city;
char *aux = (char*)malloc(TAM*sizeof(char));
p = fopen("locais.txt", "r");
while(!feof(p)){
fgetstr(linha,sizeof(linha),p); //this function removes any '\n'.It is working,because it is used for other things
strcpy(cidade->nome_cidade,strtok(linha,"#")); //This line is working as intended
printf("%s\n",cidade->nome_cidade);
strcpy(ptos->ponto.nome,strtok(NULL,"#")); //This one is not
printf("%s\n",ptos->ponto.nome); //Printing (null)
}
}
The file being read has the following format:
"#Coimbra"
"#Universidade De Coimbra#E uma das universidades mais antigas do mundo ainda em operaçao, sendo a mais antiga e uma das maiores do pais.#8:00h-18:00h#Segunda,Terca,Quarta,Quinta,Sexta,Sábado"
The output is supposed to be:
Coimbra
Universidade De Coimbra
But the actual output is just:
Coimbra

The problem isn't that strtok is returning NULL. The problem is that you never initialise ptos, so it is pointing into limbo.
Also, your function seems to take an argument pt, but you never use it.

Related

Add item sorted into a file in c

I need to take a .txt file, and check the scores that exist in it, if my score is among the top 5, add my score and my name to the file, in the correct order. But in the way I did, the append, only adds at the end. Would there be any way to check the points that are in the file, to make the comparison?
Example: If my points are greater than 40, put my name and number of points first. Leaving the rest of the list sorted again.
pedro=40
joao=32
claudio=10
joao=2
Rick=0
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
int main() {
char teste[1000], nome[20];
int meuPonto=0;
FILE *pontos;
pontos = fopen("dados.txt", "r");
if(pontos == NULL){
exit(1);
}
printf("Pontuacao atual:\n");
while(fgets(teste, 1000, pontos)){
printf("%s\n", teste);
}
printf("Digite seu nome e seus pontos:\n");
scanf("%s %i", nome, &meuPonto);
fclose(pontos);
pontos = fopen("dados.txt", "a");
fprintf(pontos, "\n%s\n%d", nome, meuPonto);
fclose(pontos);
}
The file can start at zero, but you have to save the score that was written.
Initialise an array[MAX_SCORE] with empty lines.
Add your line to the array according to your score, array[your_score].
Read each line into array[line_score].
If you get duplicates (position not empty), append the line after a LF.
Finally, print the array (backwards) to a new file (or overwrite the old file). (skip empty lines).

Why declaring multiple string arrays in one line cause initialized values to be messed up

I am declaring two arrays in my code without initializing them:
char verbe[27],
radical[27],
termi[6][4] = { "e", "es", "e", "ons", "ez", "ent" },
pronom[6][10] = { "Je", "Tu", "Il/elle", "Nous", "Vous", "Ils/elles" };
printf("entrer un verbe\n");
scanf("%s", verbe);
strncpy(radical, verbe, strlen(verbe)-2);
for (int i = 0; i < 6; i++) {
printf("%s", pronom[i]);
printf(" %s", radical);
printf("%s", termi[i]);
printf("\n");
}
when my input for verbe[] is manger, it prints:
Je mang\376e
Tu mang\376es
Il/elle mang\376e
Nous mang\376ons
Vous mang\376ez
Ils/elles mang\376ent
I can't figure out where that \376 comes from as it's supposed to print.
If I initialize verbe[] and radical[] as empty it prints the right result which is:
Je mange
Tu manges
Il/elle mange
Nous mangons
Vous mangez
Ils/elles mangent
The code snippet has undefined behavior because the arrays if they are declared in a block scope are uninitialized and you may not call printf
printf("%s ", B);
for uninitialized arrays.
This call expects that a passed array contains a string.
EDIT: After you changed your question cardinally then the array radical after the call of strncpy
strncpy(radical, verbe, strlen(verbe)-2);
does not contain a string. So this call
printf(" %s",radical);
again invokes undefined behavior.
You need to write at least like
strncpy(radical, verbe, strlen(verbe)-2);
radical[ strlen(verbe)-2 ] = '\0';
The reason for the surprising output is you use strncpy to extract the verb from the input line: strncpy(radical, verbe, strlen(verbe)-2);.
strncpy is a false friend, it does not do what you think it does. As used in your code fragment, it copies all but the last 2 bytes in the input line, presumably to strip the er at the end of the verb of the first group.
The problem is it does not add a null terminator after the bytes it copied because there is no such terminator in the part of the source string it copied. Hence the rest of the radical array is unchanged and since it is not initialized, it still contains whatever garbage is present in memory at the time your function is called. In your case there happens to be a byte with the value 0xFE and a null byte at offsets 5 and 6 of the radical array, but anything else could happen on your computer or any other computer. This is called undefined behavior, and the consequences are unpredictable.
My advice is to never use strncpy. You can learn why on this page: https://randomascii.wordpress.com/2013/04/03/stop-using-strncpy-already/
For your purpose, you can use a different technique: you can set a null terminator explicitly to strip the last 2 letters from the verb, after checking that it has indeed at least 3 letters and ends with er.
Note also that manger is not a fully regular verb: the first person plural spells nous mangeons instead of nous mangons which would be pronounced differently and be meaningless.
Here is a modified version:
#include <stdio.h>
#include <string.h>
int main() {
char verbe[27];
char radical[27];
int len;
char termi[6][4] = { "e", "es", "e", "ons", "ez", "ent" };
char pronom[6][10] = { "Je", "Tu", "Il/elle", "Nous", "Vous", "Ils/elles" };
printf("Entrer un verbe: ");
if (scanf("%26s", verbe) != 1) {
printf("fin de fichier inattendue\n");
return 1;
}
len = strlen(verbe);
if (len < 3) {
printf("verbe trop court: %s\n", verbe);
return 1;
}
if (verbe[len - 2] != 'e' || verbe[len - 1] != 'r') {
printf("pas un verbe du premier groupe: %s\n", verbe);
return 1;
}
strcpy(radical, verbe);
radical[len - 2] = '\0';
for (int i = 0; i < 6; i++) {
printf("%s", pronom[i]);
printf(" %s", radical);
if (i == 3 && radical[len - 3] == 'g') {
printf("e");
}
printf("%s", termi[i]);
printf("\n");
}
return 0;
}
Example:
Entrer un verbe: manger
je mange
tu manges
il/elle mange
nous mangeons
vous mangez
ils/elles mangent
Of course French is full of special cases, for example:
Entrer un verbe: aimer
je aime
tu aimes
il/elle aime
nous aimons
vous aimez
ils/elles aiment
the first person singular should be j'aime
Entrer un verbe: placer
je place
tu places
il/elle place
nous placons
vous placez
ils/elles placent
The first person plural should be nous plaçons
And many other exceptions, even for the first group:
jeter -> je jette
péter -> je pète
régler -> je règle
appeler -> j'appelle
marteler -> je martèle
dépuceler -> je dépucelle, mais plus moderne: je dépucèle... vive l'Académie
habiter -> j'habite
harponner -> je harponne
yoper -> je yope
aller -> je vais (pas officiellement du premier groupe)
Check this site for reference: https://leconjugueur.lefigaro.fr/conjugaison/verbe/

How do I print a char inside of an " if " in C

So I have this part of code inside the main function:
char causatxt[10];
if(causa == CCOLA){
causatxt[0] = "COLA";
}
else if(causa == CMURO){
causatxt[0] = "CHOQUE";
}
printf("\n\nEl juego ha acabado por un '%s' con los siguientes datos:", causatxt);
The problem is that I want to print the sting in causatxtbut if I define char inside the if I get a non defined error and if I do what I've pasted here I can't get causatxt to be either "COLA" or "CHOQUE".
I'm trying to avoid using a for loop to add the characters to every position of the array so I don't know if I'm supposed to use pointers because I'm not that experienced with those, but if using a for loop is the way to go then I guess I'll do that.
Thanks!
You can use strcpy from the string.h library
#include <string.h>
char a[100];
strcpy(a,"test");
Well if I understand correctly, you are experiencing a problem with setting a char* or char[] variable, that does not depend on if statement though.
If you want changeable text, I would rather use char* type. So you would write:
char* causatxt;
if(smth)
{
causatxt = "COLA"
}
You need to copt the strings.
char causatxt[10];
if(causa == CCOLA){
strcpy(causatxt,"COLA");
}
else if(causa == CMURO){
strcpy(causatxt, "CHOQUE");
}

Escape scanf within a while loop

I have this sheet of code:
listCh remplir(){
char rep;
listCh l,aux,p;
printf("1-veuillez entrer un element?(n pour quitter)\n");
scanf("%c",&rep);
if(rep=='n')
l=NULL;
else{
l=malloc(sizeof(listCh));
printf("2-Donnez la valeur d element!\n");
scanf("%d",&l->valeur);
p=l;
}
while(rep!='n'){
printf("voulez-vous ajouter un nouveau element de la list? (n pour quitter)\n");
scanf("%c",&rep);
if(rep!='n'){
aux=malloc(sizeof(listCh));
printf("Donnez la valeur d element!\n");
scanf("%d",aux->valeur);
p->suiv=aux;
p=aux;
}
else{
p->suiv=NULL;
}
}
return l;
}
There is no error while executing !
But, the problem is that my program escapes the first "scanf" function in the "while" loop.
I didn't find an explanation for this.
I need some help please.
Many thanks :)
Always remember to put a space before %c when scanf() a character variable. A bit unusual, but that's how to skip all the buffered spaces in the input stream before you can get the real character.
scanf("%c",&rep); should be scanf(" %c",&rep);
It is probably reading your enter from your first scanf.
Try putting a getchar() before your scanf on the loop

Use a single structure in C to store different structures and access them as index

I'm trying to do an Agenda with a structure, the thing is, I want it to be able to store 10 appointments and be able to access them to check them. I'm trying to do it without writing a file and reading it, I don't mind everything erases itself after the program ends.
struct Agenda{
char cita[40];
char fecha[8];
char hora[5];
};
void agregar_cita(int *num_c){
static struct Agenda x;
printf("Ingrese la cita: ");
fflush(stdin);
gets(x.cita);
printf("\nIngrese la fecha: ");
fflush(stdin);
gets(x.fecha);
printf("\nIngrese la hora: ");
fflush(stdin);
gets(x.hora);
}
I want to pass "*num_c" as a parameter and add 1 to it everytime you make a new appointment, but I can't get to access it after that.
*I'm sorry about the spanish, the function is just to add an appointment. Oh and try to use not so advanced things since I'm just recently starting to program please and thanks in advance.
Since you want multiple Agenda objects, indexed by an integer, you should declare an array. You can access elements by index, and since you're passing a pointer to the index, you can also update it from the function:
void agregar_cita(int *num_c){
static struct Agenda x[10];
printf("Ingrese la cita: ");
fflush(stdout);
gets(x[*num_c].cita);
printf("\nIngrese la fecha: ");
fflush(stdout);
gets(x[*num_c].fecha);
printf("\nIngrese la hora: ");
fflush(stdout);
gets(x[*num_c].hora);
*num_c += 1;
}
Note also that it's not useful to flush stdin, but it looks like what you really wanted was to flush stdout to ensure that your prompts appear (as shown).

Resources