I'm basically writing the code to reading things that store the rest of the string if it starts with an l. Here is my code so far:
char input[80];
char fileName[80];
fgets(input, 80, stdin); //Need to use because only want to read maximum 80 characters
if(input[0] == 'l') {
printf("String length: %d\n", strlen(input));
printf("String input: %s", input);
strncpy(fileName, &input[1], (strlen(input)) -2);
fileName[strlen(input)-1] = '\0';
printf("Filename to save: %s \n", fileName);
}
When I input ljudyjudyjudyjudy
the filename I get when I printf is judyjudyjudyjudyH
It works sometimes with different inputs, but sometimes extra characters prop up?
I think you are off by one:
fgets(input, 80, stdin); //Need to use because only want to read maximum 80 characters
if(input[0] == 'l') {
printf("String length: %d\n", strlen(input));
printf("String input: %s", input);
strncpy(fileName, &input[1], (strlen(input)) -2);
fileName[strlen(input)-2] = '\0'; // should be -2 instead
printf("Filename to save: %s \n", fileName);
}
In your example with "ljudyjudyjudyjudy" as input, you want to set fileName[16] to '\0' rather than fileName[17].
Related
I have a problem when trying to write to a txt file. I'm making a car register and after adding 2 cars to it, it looks like this in the txt file.
BMW
Car
ABCD1234
Herald
45
Fiat
Car
QWER1234
RONALD
20
My wish is to get it on the same line like this.
BMW Car ABCD1234 Herald 45
Fiat Car QWER1234 RONALD 20
This is my "save" and "add vehicle" function atm.
int save(vehicle_t * v, int count)
{
FILE * f;
f = fopen("reg.txt", "w");
if(f == NULL)
{
printf("Could not open!\n");
return 0;
}
else
{
int i;
for(i=0; i < count; i++)
{
fprintf(f, "%s %s %s %s %d\n", v[i].brand, v[i].type, v[i].reg, v[i].owner.name, v[i].owner.age);
}
}
fclose(f);
}
void add_vehicle(vehicle_t *v, int count)
{
char brand[NSIZE]; char type[NSIZE]; char reg[NSIZE]; char name[NSIZE];
int age;
printf("Brand: ");
fgets(brand, NSIZE, stdin);
strcpy(v[count].brand, brand);
printf("Type of vehicle: ");
fgets(type, NSIZE, stdin);
strcpy(v[count].type, type);
printf("Reg number: ");
fgets(reg, NSIZE, stdin);
strcpy(v[count].reg, reg);
printf("Owners name: ");
fgets(name, NSIZE, stdin);
strcpy(v[count].owner.name, name);
printf("Owners age: ");
v[count].owner.age = num_check(MAX_AGE, MIN_AGE);
}
My thought is that fgets adds \n at the end of an array, but how do I get rid of this problem when working with structs?
fgets returns all the characters on the line including the trailing \n. To keep fprintf from printing the \n characters you can change the fprintf call to
fprintf(f, "%*.*s %*.*s %*.*s %*.*s %d\n",
strlen(v[i].brand)-1, strlen(v[i].brand)-1, v[i].brand,
strlen(v[i].type)-1, strlen(v[i].type)-1, v[i].type,
strlen(v[i].reg)-1, strlen(v[i].reg)-1, v[i].reg,
strlen(v[i].owner.name)-1, strlen(v[i].owner.name)-1, v[i].owner.name,
v[i].owner.age);
This instructs it to output all but the last character of each string.
You can put the terminator one position to the left with:
fgets(name, NSIZE, stdin);
name[strlen(name) - 1] = '\0';
or you could use scanf:
scanf("%100[^\n]%*c", name);
//but here I've put a maximum 100 chars inside the string,
//not using the variable
There are other ways to do that with scanf but if you are a beginner I'd recommend you to stick with one of the two options above.
I need to read this main.txt file:
STUDENT ID 126345
TEACHER MATH CLASS 122
And i need to get each values from this file . If this main.txt file was like this:
STUDENT ID 126345
TEACHER ID 3654432
I could do it like this:
#include <stdio.h>
int main(){
FILE *ptr_file;
int id;
char string1[100],string2[100];
ptr_file = fopen("main.txt","r");
while(fscanf(ptr_file,"%s %s %d",string1,string2,id) != EOF){
}
}
But I can't use fscanf() function because space amount between these values is not equal for each line. How can i get every value in line by line like this code ?
If every line has 3 values separated by empty spaces (or tabs), then
fscanf(ptr_file,"%s %s %d",string1,string2,&id);
is OK (and note that I used &id instead of id), because %s matches a sequence of non-white-space characters, so it
doesn't matter how many empty spaces are between the values, %s will consume
the empty spaces:
#include <stdio.h>
int main(void)
{
const char *v = "STUDENT \t ID \t 126345";
int id;
char string1[100],string2[100];
sscanf(v, "%s %s %d", string1, string2, &id);
printf("'%s' '%s' %d\n", string1, string2, id);
return 0;
}
which prints
$ ./a
'STUDENT' 'ID' 126345
In general the most robost solution would be to read line by line with fgets
and parse the line with sscanf as you have more control over when a line has a
wrong format:
char buffer[1024];
while(fgets(buffer, sizeof buffer, stdin))
{
int id;
char string1[100],string2[100];
if(sscanf(buffer, "%99s %99s %d", string1, string2, &id) != 3)
{
fprintf(stderr, "Line with wrong format\n");
break;
}
// do something with read values
}
edit
User Weather Vane points out that the line might have 3 or 4 values, then you
could do this:
char buffer[1024];
while(fgets(buffer, sizeof buffer, stdin))
{
int id;
char string1[100],string2[100],string3[100];
res = sscanf(buffer, "%99s %99s %99s %d", string1, string2, string3, &id);
if(res != 4)
{
int res = sscanf(buffer, "%99s %99s %d", string1, string2, &id);
if(res != 3)
{
fprintf(stderr, "Line with wrong format, 3 or 4 values expected\n");
break;
}
}
if(res == 3)
printf("'%s' '%s' %d\n", string1, string2, id);
else
printf("'%s' '%s' '%s' %d\n", string1, string2, string3, id);
}
Is there a way to make this error checking any better? Or is there something I am forgetting? I am expecting an integer then string. I added the suggestions to the code.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>
int main(void) {
// your code goes here
char line[150] = {0};
int sscanf_counter = 0;
int num = 0;
char string[150] = {0};
char dummy;
while(fgets(line, sizeof line, stdin))
{
printf("line is %s\n", line);
sscanf_counter = sscanf(line, "%d %s %c", &num, string, &dummy);
printf ("sscanf_counter: %d\n", sscanf_counter);
if (sscanf_counter == 2 && isalpha(string[0]))
{
printf ("Good value: %d\n", num);
printf ("string: <%s>\n", string);
}
else
{
printf ("BAD VALUE: %d \n", num);
printf ("string: <%s>\n", string);
}
memset(line, 0, sizeof line);
}
printf("Does this print? \n");
return 0;
}
I didn't want 222 to be converted to a string so I added a simple isalpha() check to my code. I want an actual number for my first value and actual alphabet characters not numbers converted to a string for the second value.
Output with small tweak:
aaa aaa
line is aaa aaa
sscanf_counter: 0
BAD VALUE: 0
string: <>
111 222
line is 111 222
sscanf_counter: 2
BAD VALUE: 111
string: <222>
111 aaa
line is 111 aaa
sscanf_counter: 2
Good value: 111
string: <aaa>
Is there a way to make this error checking any better?
"%d" is not specified on overflow. Stronger error checking can be provided with strtol().
"%d %s" does not detect extraneous extra input.
To deal with extra input and still use sscanf(), see below. If sscanf_counter == 3, extra non-white-space input detected.
char dummy;
sscanf_counter = sscanf(line, "%d %s %c", &num, string, &dummy);
The test if (sscanf_counter == ...) should happen before using the variables.
printf ("sscanf_counter: %d\n", sscanf_counter);
if (sscanf_counter >= 1) printf ("num: %d\n", num);
if (sscanf_counter >= 2) printf ("string: %s\n", string);
Tip: when printing a string, consider printable sententials to help detect leading/trailing white-space issues. (Even though these are not expected with "%s".)
// printf ("string: %s\n", string);
printf ("string: <%s>\n", string);
OT: Rather than code magic numbers, use code that adapts
// memset(line, 0, 150);
memset(line, 0, sizeof line);
// while(fgets(line, 150, stdin) != NULL)
while (fgets(line, sizeof line, stdin))
Sorry for a stupid question, but this is really starting to annoy me.
I need to take a line of input from a console. Here's the relavent fragment of code:
int number_read=0;
char line[80];
printf("Enter register address: ");
number_read = scanf("%s\n", line);
printf("number of characters entered: %d; characters entered: %s.\n", number_read, line);
if (number_read > 0) {
<read some registers and display the results.>
}
It doesn't work. The "Enter register address" line is printed, and the cursor stops at the end of the line, and moves to the next line when I press enter, but then nothing else happens. I've tried replacing scanf() with fscanf(stdin,...), with fgets(stdin), gets, GNU's getline(), a short function that does the same thing, with diagnostics:
char *new_line, ch;
for(;;) {
ch = fgetc(stdin);
if(ch == EOF) break;
if((*line++ = ch) == '\n') break;
printf("Line so far: %s\n", line);
}
*line='\0';
I get the same response from all of them. I'm including all the requisite headers.
I'm on a Windows XP box, compiling with gcc 3.4.5 (mingw).
Can anyone see what I'm doing wrong?
In scanf you should use a %i to represent a int so, try with
scanf("%I", number_line);
The following code will works,
char buff_msg[1024];
while(1)
{
if(fgets(buff_msg,1024, stdin) != NULL){
printf("%s\n", buff_msg);
memset(buff_msg, 0, 1024); // you will need this line
}
}
You can
break the loop on your own condition
try read() it works in MinGW replace
this
number_read = scanf("%s\n", line);
with this also include #include<unistd.h>
number_read = read(STDIN_FILENO, (void *)line,sizeof line);
value scanf returns is not the number of strings in the number of elements to read(this case meybe 1).
Use the %n To get the number, such as desired.
scanf("%s%n", line, &number_read);
printf("number of characters entered: %d; characters entered: %s.\n", number_read, line);
#include
char option[64],line[256];
main()
{
printf(">>")
(fgets(line, sizeof(line), stdin)) {
if (1 == sscanf(line, "%s", option)) {
}
}
print(option)
}
will only get the first word, for example
/>>hello world
would output
/>>hello
#include <stdio.h>
int main(){
char option[64],line[256];
printf(">>");
if(fgets(line, sizeof(line), stdin)) {
if (1 == sscanf(line, "%[^\n]%*c", option)) {//[^\n] isn't newline chars
printf("%s\n", option);
}
}
return 0;
}
In sscanf(..., "%s" ...
The scan terminates at whitespace, if you want to print entire line you just have to:
printf("%s", line)
You can use a format in scanf that allows you to match whitespaces. Look at #BLUEPIXY good anwser.
Alternatively, you can use getline(). More info here.
You can try the following code snippet :
char dump, string[40];
printf("Enter the sentece with spaces:\n");
scanf ("%[^\n]", string);
scanf("%c", &dump);
printf ("You entered: %s", string);
getchar();
getchar();