Reputation: 21
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
Upvotes: 1
Views: 345
Reputation: 144999
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:
Check this site for reference: https://leconjugueur.lefigaro.fr/conjugaison/verbe/
Upvotes: 0
Reputation: 311088
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';
Upvotes: 2