getting numbers from stdin to an array in C - arrays

I'm trying to get numbers from stdin to an array. the first number in stdin is the number of elements in the array (the number can be any int).
I did this to get the first number:
while(c=getchar()!=' '){
n*=10;
n+=atoi(c);
}
And then created an array of size n.
Now I need to go through all the rest
while(c=getchar()!=EOF)
and add numbers to the array. The numbers are separated by \t and sometimes \n as well.
How would I do that? I've been thinking for an hour and still haven't got a working code.
Any help?
Thanks!

Unless you're feeling particularly masochistic (or can't due to homework requirements), you'd normally do it using scanf:
int n;
int *numbers;
scanf("%d", &n);
numbers = malloc(n * sizeof(*numbers));
for (int i=0; i<n; i++)
scanf("%d", &numbers[i]);
For more robust error handling, you frequently want to read a line at a time using fgets, then parse that into individual numbers using sscanf (or something similar).
As an aside: no you should not cast the return from malloc to int *. It's neither necessary nor desirable in C. Just #include <stdlib.h>, and assign the result as shown above. If your compiler is giving you a warning (or error) about a conversion, that means one of two things is happening: either you've forgotten to #include <stdlib.h> as required, or else you're actually compiling as C++. If you're writing C++, write real C++, which means you shouldn't be using malloc at all.

Related

Runtime error when using char as int to scanf and printf

int main()
{
char ch = 0;
int c = 0;
scanf("%d", &ch);
printf("%c", ch);
}
I can input the ASCII number and output the correct character. But the program crashes at the end of the code, the } sign.
Using Visual Studio 2019
Run-Time Check Failure #2 - Stack around the variable 'ch' was corrupted.
Since scanf has non-existent type safety, it can't know the type of parameters passed (one reason why the format string is there in the first place).
The stack corruption is caused by you lying to the compiler here: scanf("%d", &ch);. You tell it "trust me, ch is an int". But it isn't. So scanf tries to store 4 bytes in an area where only 1 byte is allocated and you get a crash.
Decent compilers can warn for incorrect format specifiers.
There are multiple problems in your code:
missing #include <stdio.h> ;
unused variable c ;
type mismatch passing a char variable address when scanf() expects an int * for the %d conversion specifier ;
missing test on scanf() return value ;
missing newline at the end of the output ;
missing return 0; (implied as of c99, but sloppy).
Here is a modified version:
#include <stdio.h>
int main() {
int ch;
if (scanf("%d", &ch) == 1) {
printf("%c\n", ch);
}
return 0;
}
I guess your question was not, "What did I do wrong?", or "Why didn't it work?".
I guess your question is, "Why did it work?", or, "Why did it print an error message after seeming to work correctly?"
There are lots of mistakes you can make which will corrupt the stack. This is one of them. Much of the time, these errors are rather inscrutable: If the memory corruption is severe enough that the memory management hardware can detect it, you may get a generic message like "Segmentation violation" at the instant the bad access occurs, but if not, if the damage isn't bad enough to cause any overt problems, your program may seem to work as you expected, despite the error.
It would be prohibitively expensive to perform explicit tests (in software) to check the stack for damage during every operation. Therefore, no attempt is made to do so, and the primary responsibility is placed on you, the programmer, not to do obviously wrong things like telling scanf to store an int in a char-sized box.
In this case, your system did make a check for stack damage, but as some kind of a one-time operation, only after the main function had returned. That's why the scanf and the printf seemed to work correctly, and the error message seemed to coincide with the closing } at the end of main.
Echoing an analogy I made in a comment, this is sort of like having a policeman write you a ticket for having done something dangerous that did not cause an accident. Why not write the ticket as you are doing the dangerous thing? Why write the ticket after the fact at all, since your dangerous behavior didn't cause an accident? Well, because sometimes that's just the way the world works.
I think you are trying to input an integer and print its char value so in my opinion this is what you are trying to do:
#include <iostream>
using namespace std;
int main()
{
int c = 0;
scanf("%d", &c);
printf("%c", c);
return 0;
}
Note: This is a C++ code but the syntax inside main function will work for C language as well

Error: expected declaration specifiers or '...' before string constant [puts() and gets() statement errors

After compiling my program of Dice Roll, I got this error. What is wrong with the code?
Also before I was using gets() instead of scanf() command, but because of that I got this error - passing argument 1 of 'gets' makes pointer from integer without a cast
So I removed the gets() command and used scanf and then there was no error regarding scanf().
What is the reason for getting these two errors?
Ok, so as per the answer I got to know how I should have used the gets() command and why I shouldn't use it instead should use scanf(). So, I made the changes.
Though I have encountered two new errors, this time it's related to the delay() command that I used.
Errors: undefined reference to delay
|error: ld returned 1 exit status|
OK so I solved my last errors by using Sleep() command from windows.h library instead of Delay() command. The programs was compiled.
But still there is a runtime error in the program, it works well till getting the roll1 but then it just print the next two statement and terminated the programs without taking a input for the guess.
It skips all the code after printf("Will it be Higher/Lower or the same? (press H/L/S)\n"); and directly terminates the program.
Ok So I solved above problem adding a whitespace before the "%c" in scanf(" %c", &nextGuess); statement. (Little things xD)
Now only problem is that my toupper() command is not working.
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <windows.h>
int main()
{
int i, roll1=0, roll2=0, NumberOfRolls, RandomNUM1[50], RandomNUM2[50];
char nextGuess;
puts("Welcome to the Dice Roll Game");
puts("How many times do you want to roll a dice?");
scanf("%d", &NumberOfRolls);
for( i=1; i<=NumberOfRolls; i++ ) {
RandomNUM1[i] = ( rand()%6 ) + 1;
roll1 += RandomNUM1[i];
}
printf("\nYou Got %d in your first roll!\n", roll1);
Sleep(3000);
printf("\nLet's see if you can guess the value of next roll.\n");
printf("Will it be Higher/Lower or the same? (press H/L/S)\n");
scanf(" %c", &nextGuess);
toupper(nextGuess);
for( i=1; i<=NumberOfRolls; i++ ) {
RandomNUM2[i] = ( rand()%6 ) + 1;
roll2 += RandomNUM2[i];
}
if(nextGuess=='H'){
if(roll1<roll2){
printf("You are such a player, you guessed it right! It's %d", roll2);
}
else if(roll1>roll2){
printf("Uh-Oh! Bad Luck! First roll was higher, It's %d", roll2);
}
else if(roll1==roll2){
printf("Uh-Oh! Bad Luck! Both the rolls are same, It's %d", roll2);
}
}
if(nextGuess=='L'){
if(roll1>roll2){
printf("You are such a player, you guessed it right! It's %d", roll2);
}
else if(roll1<roll2){
printf("Uh-Oh! Bad Luck! First roll was lower, It's %d", roll2);
}
else if(roll1==roll2){
printf("Uh-Oh! Bad Luck! Both the rolls are same, It's %d", roll2);
}
}
if(nextGuess=='S'){
if(roll1==roll2){
printf("You are such a player, you guessed it right! It's %d", roll2);
}
else if(roll1>roll2){
printf("Uh-Oh! Bad Luck! First roll was higher, It's %d", roll2);
}
else if(roll1<roll2){
printf("Uh-Oh! Bad Luck! Second roll is higher, It's %d", roll2);
}
}
return 0;
}
You have a stray ,
At the 2nd line of your main, you declare char nextGuess, instead of char nextGuess;
The compiler tells you it expects specifiers or ... after , so either you add these, or you end the line properly with;.
And for the other problem you mention:
passing argument 1 of 'gets' makes pointer from integer without a cast
Since gets argument should be char *str and you didn't provide it.
You can fix that by, for example:
char tmp_NumberOfRolls[10];
gets(tmp_NumberOfRolls);
NumberOfRolls = atoi(tmp_NumberOfRolls);
but I prefer the scanf solution
PS: (in a now edited version of the code) ***//Error Line*** is not a comment (at least, not all of it) since the *** is still counted as part of the code and will cause an error. Either move the // a bit to the left or enclose that whole part with /* ... */
The gets function reads a string (till the next newline character) from stdin, therefore it asks for a char pointer (char*) to an area of memory where it can put all the characters read including string terminator. The mistake you made is to pass to that function a pointer to int, therefore not only you get a compiler error because you tried to pass an int pointer to gets (for which there are none implicit conversions), but even if it compiled, it would not have worked as you expected because it would put all the characters (which have a size of one byte - most of the times) in that area of memory encoded as chars. That means that when you try to dereference one using a pointer to int, the characters are "read like they were an int"!
There is an example (supposing 1-byte chars, 4-bytes int and a little endian machine and that there is an implicit cast from int* to char* which does not exist and hopefully will never exist):
int num
gets(&num);
if I input 123 in stdin, the memory area pointer by num is large enough to contain the string, but it would contain (exadecimal representation):
0x31|0x32|0x33|0x00
because the string is 3 characters long, ASCII code for '1' is 0x31, for '2' is 0x32, and for '3' is 0x33 and terminates with '\0'!!
Then, when you try to dereference it you get this int (binary representation - supposing a little endian machine):
00000000|00110001|00110010|00110011
which is not the int value 123 but instead ‭3224115‬. Which is not what you wanted to get.
When you use the scanf function, you pass to that function a format string which tells it how to interpret the next arguments passed to it and performs the appropriate conversions between the string read to the right type you specified. That means that you should still pay attention to what you tell to the scanf function while you write the format string (if you tell it to read a string and pass to it a pointer to int, the program will probably crash), but it performs the appropriate conversions for you, if you write the format string correctly.
That's why with scanf everything works perfectly (you're reading an int and you specified "%d" as format string), whereas with gets it does not compile to avoid serious mistakes.
I also would like to remark some points of this answer:
The example is just for didactic purposes and the code provided does not work indeeed. The fact that I supposed that it compiles is for didactic purposes; obviously, the code provided in that example does not compile
If, in that example, we input a string larger than 3 characters (which are four if we include the null terminator) or the int (char) type contains less (more) than 4 (1) byte, the program would have crashed because we corrupted other areas of memory
The reference is more expert than me in techincal stuff, so here are the links to the gets function and the scanf function: gets, scanf (and the ASCII Table is useful too)
You could use the gets function together with the atoi function to parse the string read from gets (using a char pointer to a free area of memory large enough to contain the string, which is pretty hard to allocate (*)) to an int, but scanf is the best approach.
(*) Remember: if you allocate an area of memory that contains 20 chars, the user will input 21 chars. The atoi function fails, but the worst thing is that you have a buffer overflow (and can be a high security issue if your program runs under root permissions).

printing multiple integers at the same time

I was wondering if there is a better way to print an array of ints in c;
At the moment I do a printf("%d" ,.. ) for every int in my array.
However this causes one system call per int? (if my understanding is correct).
It would be better to convert the int array to string buffer and then print the buffer in one call.
I can write the code for it if necessary.
Q1. is this a good idea or too much hassle to be worth it?
Q2. Are there any libraries that implement such a thing. (Whatever I google comes back to beginners tutorials for printing integers :s)
Edit
The size of the array is not known before hand.
No, it does not cause one system call per int, unless you set stdout to unbuffered mode. This is the whole point of stdio: to buffer output for you so you don't have to do it yourself. There is a minimal amount of additional call overhead for the printf function itself. If you find yourself needing more performance, you could try something like:
for (i=0; i+4<=N; i+=4)
printf("%d %d %d %d ", a[i], a[i+1], a[i+2], a[i+3]);
for (; i<N; i++)
printf("%d ", a[i]);
When you use printf, the output is already buffered. The system call is made only when you "flush" the buffer - either explicitly by calling fflush(stdout) or implicitly by printing \n to a console. Therefore, pre-buffering on the application side will make your code more complex without offering any real difference in performance.
As far as a library to help you write ints to a string goes, you can use the same <stdio.h> that you are already using: allocate a buffer sufficiently large to hold your integers, use sprintf instead of printf to write to it, and then call printf with the content of the entire buffer. This would help you avoid flushing on \n, should you decide to use them as separators in your output.

C - Error while running .exe file that I compiled

I used geany to compile my code and no errors were found.
But when I run the .exe file the program stops working, and I'm not a good programmer, this is a work for school.
My program consists of reading 2 words, in this words its going to count how many letters each one has, and then he divides de number of letters in wordA for number of letters in wordB.
This is my code
#include <stdio.h>
int main(int argc, char *argv[])
{
int i, j;
float n;
printf ("Insert first word:\n");
for(i=0; argv[1][i] != '\0'; i++);
printf ("Insert second word:\n");
for(j=0; argv[2][j] != '\0'; j++);
n=i/j;
printf("%.4f", n);
return 0;
}
In this line
n = i/j;
you are performing integer division. So, for example, let's say that i is 3 and j is 5, then you perform 3/5 which equals 0.
But I think you are looking to perform 3.0/5.0 and hoping for the answer 0.6. So you need to perform floating point division. You can force that by casting one of the operands to a float.
n = (float)i/j;
In the question you wrote Int rather than int. I assumed that was a transcription error when asking the question. But perhaps your real code looks like that. In which case, you'll need to change it to int to get it to compile.
The other possible problem you have is that the program expects arguments to be passed on the command line. Are you passing two arguments to your program? In other words you need to execute your program like this:
program.exe firstword secondword
If you are not passing arguments then you will encounter runtime errors when attempting to access non-existent arguments in argv[]. At the very least you should add a check to the program to ensure that argc==3.
If you want to read the input from stdin, rather than passing command line arguments, use scanf.
I think this is a conceptual error. Your program (probably) runs fine when called like this:
myapp word1 word2
But I think you expect it to work like this:
myapp
Insert first word:
> word1
Insert second word:
> word2
But that's not what argv is about. You should look into scanf
Specifically, the error in the second case is because argv[1] is NULL, so argv[1][i] is a bad memory access.

Provide integer arrays as input from command line

I'm writing a program to access a bin packing algorithm function from a library, I haven't done much with it since college so my C is a bit rusty. The function I'm calling requires I pass in 3 different integer arrays. I'll be calling this from the command line. Should I use argv? Or STDIN? The input arrays could potentially be 50 to 100 elements each. Either way I suppose I will have to write something to parse the strings and get them into arrays, is there an easy way to do that?
For big arrays, I'd rather use standard input, as there are usually operating system limits to how many arguments you can have.
You will also need some kind of input format. Let's say the first number n is the number of elements in the first array, followed by the element values, and so on. Then I'd do something like:
#include <stdlib.h>
#include <stdio.h>
int main()
{
// you need to implement read_number yourself
int n = read_number(stdin);
// allocate array
int *array = (int*) malloc(n*sizeof(int));
// read n numbers into array
for ( int i=0; i < n; ++i )
array[i] = read_number(stdin);
// and so on...
}
You get the general idea. You'd either have to implement read_number yourself or find examples on the net on how to do it. You will need to discern individual numbers somehow, e.g. by parsing each digit up to the next white space character. Then you can separate each digit on stdin by space characters.
For instance, you can use #ypnos suggested scanf solution below.
For that amount of elements you should use stdin. Nobody will type them in by hand anyway and ./program < file is as easy as it gets.
The parsing is no big deal with scanf. Just define that your input should include the number of elements before all the numbers forming an array. Then you can scanf("%d", &elemcount), and then for-loop over elemcount, again using scanf.
The beauty of it is that scanf will deal with all the whitespaces, newlines etc. the user may put in between the numbers of elements and the other numbers.

Resources