Reading numbers from command line in c - c

Assuming I have a variable:
char variableName[256];
How can i store input from the command line if i'm given a list of numbers like 10 11 12 .. etc. I'm using
fgets(variableName, sizeof(variableName), stdin)
and its turning it directly into (1,0,1,1, etc) as opposed to the converting between the spaces to (10, 11, 12, etc).
Should I perhaps use scanf, and store based of white space; Just unsure of the syntax/what is common?
Thanks guys!

if you know how many numbers will be inputed then use sscanf after using fgets or use scanf directly (not recommended)
int var[NO_OF_INPUTS];
fgets(variableName , sizeof variableName , stdin);
sscanf(variableName , "%d %d %d ... %d" , &var[0] , &var[1] , ... , &var[NO_OF_INPUTS - 1]);
if you don't know the number of inputs then you can make a function that counts how many numbers were entered by counting the number of whitespace after fgets then maybe use strtok to jump between whitespace and strtol to convert that into a number

If you are getting values from command line then you can simply do the job by using argc, argv and strtol. No need to create new variables!
argc contains the number of command line argument passed to your program.
argv is the array of arguments.
I hope this code will help:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
int i;
char *p;
long int li_arr[argc];
if (argc==1)
{
puts("No arguments provided");
exit(1);
}
for(i=1;i<argc;i++)
{
li_arr[i] = strtol(argv[i],&p,10);
printf("%ld\n",li_arr[i]);
}
return 0;
}

You don't have to call fgets or any other function because arguments passed to program are in argv[] array. You can acces them directly just with
int i = atoi( argv[1]);
but better you should use sscanf which provides error checking:
if ( sscanf ( argv[1], "%d", &i) != 1) { printf ( "error - not an integer"); }
or strtol() which prevents under/overflow:
char *endptr, *str;
str = argv[1];
long val = strtol( str, &endptr, 10);
http://linux.die.net/man/3/sscanf

Related

get multiple inputs in one line C

int main(){
char *inputFile;
char *outputFile;
int numberOfBuffer;
int pageSize;
printf("Enter four inpus, separated by spaces: ");
scanf("%s %s B=%d P=%d", &inputFile,&outputFile,&numberOfBuffer,&pageSize);
readCSV(inputFile,outputFile,numberOfBuffer,pageSize);
return 0;
}
I want to read inputs and run readCSV() method with entering command line to
students.csv test.csv B=5 P=32
that line but my code does not work. Any help?
readCSV() input types
readCSV(char* fileName,char* outputFileName, int numberOfBuffer, int pageSize)
You invoked undefined behavior by passing data having wrong type to scanf(): %s expects char* (pointing at a valid buffer with enough length), but you passed char**.
You should allocate some arrays and pass pointers to them. Arrays in expressions (except for some exceptions) are automatically converted to pointers to its first elements, so you don't need explicit & for them.
Also you should specify the maximum length to read (at most the buffer size minus one for the terminating null-character) to avoid buffer overrun and check if scanf() succeeded to read all required things.
int main(){
char inputFile[1024];
char outputFile[1024];
int numberOfBuffer;
int pageSize;
printf("Enter four inpus, separated by spaces: ");
if(scanf("%1023s %1023s B=%d P=%d", inputFile,outputFile,&numberOfBuffer,&pageSize) != 4){
fputs("read error\n", stderr);
return 1;
}
readCSV(inputFile,outputFile,numberOfBuffer,pageSize);
return 0;
}
Both inputFile and outputFile need to be declared as arrays of char large enough to hold the expected inputs1:
#define MAX_FILE_NAME_LENGTH some-value
...
char inputFile[MAX_FILE_NAME_LENGTH+1]; // +1 for string terminator
char outputFile[MAX_FILE_NAME_LENGTH+1];
Then in the scanf call, do not use the unary & operator for inputFile and outputFile - when you pass an array expression as an argument, it automatically gets converted to a pointer to the first element of the array. You also want to check the result of scanf to make sure you got all your inputs:
if ( scanf( "%s %s B=%d P=%d", inputFile, outputFile, &numberOfBuffer, &pageSize ) != 4 )
{
// bad input somewhere, probably with numberOfBuffer or pageSize,
// handle as appropriate
}
else
{
// process input normally
}
But...
scanf is an awful tool for doing interactive input. It is very hard to make bulletproof, and for stuff like this you're really better off reading the whole thing as a single large string using fgets or something like that, then extracting data from that string.
One thing that may help simplify this for you is that you don't have to read the entire line in a single scanf call. You can read each element individually:
/**
* Start by reading the input file name; we use `fgets` instead
* of `scanf` because it's easier to protect against a buffer overflow
*/
if ( !fgets( inputFile, sizeof inputFile, stdin ) )
{
// error reading input file name, handle as appropriate
}
/**
* Successfully read inputFile, now read outputFile
*/
else if ( !fgets( outputFile, sizeof outputFile, stdin ) )
{
// error reading output file name, handle as appropriate
}
/**
* Now get the number of buffers - the leading blank in the format
* string tells scanf to skip over any leading whitespace, otherwise
* if you have more than one blank between the end of the output file
* name and the 'B' the read will fail.
*/
else if ( scanf( " B=%d", &numberOfBuffer ) != 1 )
{
// error getting number of buffers, handle as appropriate
}
/**
* And finally the page size, with the same leading blank space in the
* format string.
*/
else if ( scanf( " P=%d", &pageSize ) != 1 )
{
// error getting page size, handle as appropriate
}
else
{
// process all inputs normally.
}
Or the memory for them needs to be allocated dynamically, but as you're just learning C that's something to tackle later on.
Most of your issues are caused by misuse of scanf. The solution here is not to fix your usage of scanf, but to avoid it completely. (http://sekrit.de/webdocs/c/beginners-guide-away-from-scanf.html) Parameters like this should come from the command line arguments, not from the input stream. It is almost always better to leave the input stream clear so that it can be used for collecting data. (eg, write your program as a filter.) For example:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
static void
check_prefix(const char *a, const char *prefix)
{
if( strncmp(a, prefix, strlen(prefix)) ){
fprintf(stderr, "Invalid argument: %s Must start with, %s\n",
a, prefix);
exit(EXIT_FAILURE);
}
}
static void
readCSV(const char *in, const char *out, int n, int p)
{
printf("in = %s, out = %s, n = %d, p = %d\n", in, out, n, p);
}
int
main(int argc, char **argv)
{
if( argc < 5 ){
fprintf(stderr, "Invalid number of arguments\n");
return EXIT_FAILURE;
}
check_prefix(argv[3], "B=");
check_prefix(argv[4], "P=");
char *inputFile = argv[1];
char *outputFile = argv[2];
int numberOfBuffer = strtol(argv[3] + 2, NULL, 10);
int pageSize = strtol(argv[4] + 2, NULL, 10);
readCSV(inputFile, outputFile, numberOfBuffer, pageSize);
return 0;
}

scan a sequence of lines of strings with white spaces

My code is for reading an input of strings and newline is used as delimiter. But my code doesn't read the inputs correctly and the output is different from the input. In my code i used %*[\n]c to read the newline character for if any present and skip it so that it is not included while reading the next string.
#include<stdio.h>
main()
{
char s[100],s1[100],s2[100];
scanf("%[^\n]s%*[\n]c%[^\n]s%*[\n]c%[^\n]s%*[\n]c",s,s1,s2);
printf("%s%s%s",s,s1,s2);
return 0;
}
My inputs for this program are below:
this is 1st line
this is 2nd line
this is 3rd line
My output is
this is 1st line.N=ö
Can someone correct my code.Thank you.
In the posted code, there is a risk of buffer overflow since no maximum width is specified for the input buffers. Such widths should always be specified for safe code; remember to leave space for the null character that terminates the string.
scanf(" %99[^\n] %99[^\n] %99[^\n]", s, s1, s2);
The fgets() function is better suited to read lines of input. Note that fgets() keeps the newline when it reads a line of input, so you may want to remove this in some cases. Also, if the user inputs more characters than will fit in the specified buffer, the newline and some characters will remain in the input stream. But this is no different than using scanf(), in that one must always be careful about what may be left behind in the input stream after an IO operation. In any event, using fgets() is generally less error-prone than using scanf(), and there is benefit in having user input stored in a string. The sscanf() function can always be used on the string obtained with fgets(), but in this case you still have the input string to work with after calling sscanf().
Also, note that the function signature in the OP code needs to be one of:
int main(void)
int main(int argc, char **argv)
int main(int argc, char *argv[])
Here is an example using fgets() to read and then display lines of input:
#include <stdio.h>
#include <stdlib.h>
#define MAXLINES 25
#define BUF_LEN 1000
int main(void)
{
char lines[MAXLINES][BUF_LEN];
size_t num_lines = 0;
puts("Enter some lines of text (empty line to quit):");
for(num_lines = 0; num_lines < MAXLINES; num_lines++) {
if (fgets(lines[num_lines], BUF_LEN, stdin) == NULL) {
fprintf(stderr, "Error in fgets\n");
exit(EXIT_FAILURE);
}
if (lines[num_lines][0] == '\n') {
break;
}
}
for (size_t i = 0; i < num_lines; i++) {
printf("%s",lines[i]);
}
return 0;
}
#include<stdio.h>
main()
{
char s[100], s1[100], s2[100];
scanf("%[^\n] %[^\n] %[^\n]", s, s1, s2);
printf("%s\n%s\n%s\n", s, s1, s2);
}

sscanf reading in wrong values

Fairly new to C and am trying to parse input from a file. I have no problems getting the operation and address fields but I am getting the value "32767" for the size field.
Here is the code causing issues:
#include <stdio.h>
#include <string.h>
void read_file(char *filename)
{
// operation field, address field, size field
FILE *file = fopen(filename, "r");
char buff[25];
char operation;
long address;
int size;
char *cur_trace = fgets(buff, 25, file);
while (cur_trace) {
// read indivdual fields of trace
// if cur_trace[0] == I then ignore line
if (cur_trace[0] != 'I') {
sscanf(cur_trace, " %c %lx[^,]%*c%u", &operation, &address, &size);
printf("operation: %c\n address: %lx\n size: %u\n", operation, address, size);
}
cur_trace = fgets(buff, 25, file);
}
}
int main(int argc, char const *argv[])
{
read_file("tester.txt");
return 0;
}
and here is the input text I am reading. All lines beginning with 'I' are being ignored.
I 0400d7d4,8
M 0421c7f0,4
L 04f6b868,8
S 7ff0005c8,8
The brackets is not a generic part of the format string, it's part of a specific scanf format code to read strings. It can't just be placed anywhere as a sort of pattern, or used for any other format.
And by the way, reading hexadecimal values will stop at the first non-hexadecimal character, so you don't need it anyway. Just doing e.g.
sscanf(cur_trace, " %c %lx,%u", &operation, &address, &size);
should be enough (if the types of the variables are correct).
The problem is that your format string is not parsing the 3rd argument &size, because of the format string.
The 32767 value is just uninitialized junk.
You need to check that sscanf returns 3 so that all arguments are accounted for.

using sscanf() read from command line [duplicate]

I need to get argv[1] and argv[2] to different types. I found that I could only use sscanf() once or the next string in argv cannot be retrieved.
Here's my code.
int main( int argc, char *argv[])
{
char t;
float temp;
sscanf(argv[1], "-%[cf]",&t);
sscanf(argv[2], "%f", &temp);
return 0;
}
Only the first sscanf() can get the formatted value.
How could I also get done with argv[2]?
Attempt to save string data in a char leading to undefined behavior (UB).
"%[]" expects to match a character array.
// char t;
// sscanf(argv[1], "-%[cf]",&t);
char t[100];
if (sscanf(argv[1], "-%99[cf]",t) != 1) Handle_Failure();
Recommend:
Add the width limit, like 99, to limit string input. Set to 1 less than the size of t.
Check the return value of sscanf().

fgets give me random big number

This is my code, I don't know how to use fgets after scanf so I am using fgets in the 26th line too but every time I use it, it give me big number(ex.2752100) but I write 2.
Why is it doing it?
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char** argv)
{
char veta[100];
int line = 1;//tell what line it is on
int found = 0;
char a[100];//put the characters of the line into here
char b[100];
char linesearch[10];//the line you are looking for
FILE *file;//the file pointer
file = fopen("text.txt","r");//point the file
if (file == NULL)
{
printf("file does not exist or doesn't work\n");
return 0;
}
printf("Ahoj, naucim te psat snadno a rychle! \n");
printf("Vyber si uroven slozitosti od 1 do 10:\n");
//scanf("%d", &linesearch);
fgets(linesearch,10,stdin);
printf("\nHledam uroven %d ...\n\n",linesearch);
EDIT:
i have another problem:
while(fgets(a,100,file))
{
if(x == line)
{
found = 1;
printf("level %d found,level %d say: %s",x,x,a);
}
else
printf("reading level: %d\n",line );
line++;
}
printf("\nwrite your string as fast as you can!!");
fgets(veta,40,stdin);
if (strcmp(veta,a) == 0)
{
printf("\nwell done!!!!\n");
}
else
{
printf("\nwrong!!!!\n");
printf("%s", a);
printf("%s", veta);
}
i have small senteces(ex I like my mum and she likes me,etc) i want to compare my text with text from file and get answer if I write it well or not. Bonus points if it tell me how many mistakes i did it will be powerful!.
The fgets() function reads character data from the input. To convert this character data to an integer, use atoi() or a similar function.
fgets(linesearch, 10, stdin);
int x = atoi(linesearch);
printf("\nHledam uroven %d ...\n\n",x);
Your printf statement is printing out the address of the linesearch array, which will seem like a random big number.
If you want to read from stdin, into a char array, using scanf() and then print as an int:
scanf("%s", linesearch); // e.g. reads 1234 into array linesearch[].
printf(" %s ...\n\n",linesearch); // Prints string in array linesearch[].
printf(" %p ...\n\n",linesearch); // Prints base address of linesearch[].
int iNum = atoi(linesearch); // Converts string "1234" to number 1234.
printf(" %d ...\n\n",iNum); // Prints the converted int.
iNum++; // Can perform arithmetic on this converted int.
You are getting a big number from printf because you used %d in the format. The number is the memory address of your character array. To print the character array, update the format to %s.

Resources