Last element is missing from the 2D array - c

Code:
#include <stdio.h>
int main(){
int num;
scanf("%d", &num);
printf("Enter: ");
char nums[5][num], ch;
for(int i = 0; i < num; i++){
for(int j = 0; j < 5; j++){
if((ch = getchar()) != '\n'){
nums[j][i] = ch;
}
}
}
for(int i = 0; i < num; i++){
for(int j = 0; j < 5; j++){
printf("%c ", nums[j][i]);
}
printf("\n");
}
return 0;
}
Output:
1
Enter: 12345
1 2 3 4
Process returned 0 (0x0) execution time : 6.282 s
Press ENTER to continue.
Why the last element is missing and the additional space at the beginning of the output of array?
If I change the range for j in both for loops to
j <= 5
then, the output looks like this:
1
Enter: 12345
1 2 3 4 5
Process returned 0 (0x0) execution time : 2.107 s
Press ENTER to continue.
If the initial value for j is 1 in the printf loop, then the output looks like this:
1
Enter: 12345
1 2 3 4 5
Process returned 0 (0x0) execution time : 3.675 s
Press ENTER to continue.
No extra gap at the beginning of the array output.
Can anyone explain this and how to resolve this problem?

The problem is that the function getchar reads all characters from the input stream including the new line character that stored in the buffer after the first call of scanf.
So in the loops the first character that is read is the new line character '\n'.
You should remove it for example the following way.
scanf( "%*[^\n]" );
scanf( "%*c" );

You have a logic issue in the first loop. You test for \n but then if you do find a \n, you leave the array entry uninitialized and go on to the next entry anyway. This leads to the bogus output.
Instead you could delay the j++ until getting a valid character, e.g. :
for(int i = 0; i < num; i++){
for(int j = 0; j < 5; ){
if((ch = getchar()) != '\n'){
nums[j][i] = ch;
++j;
}
}
}
Then the array will be filled with the non-newline characters that get entered, and you don't need to do any other flushling.
It would improve the code to also check ch != EOF (and ch should be declared as int), but then you will need some error handling (it would be a mistake to just break the loop and go on to try and output the whole array).

Related

For loop doesn't increment indexes properly

I'd like to store input from keypad in array, but my for loop doesn't seem to work properly. Instead of reading an input from keypad, adding it to the array, and then incrementing the index, the program keep printing weird indexes.
Code
void loop(){
char arr[3];
for (int i = 0; i<3; i++){
char input = customKeypad.getKey();
if (input != NO_KEY){
do{
arr[i] = input;
Serial.println("Index");
Serial.println(i);
Serial.println("Value");
Serial.println(arr[i]);
} while(input == NO_KEY);
}
}
}
Console output
Index
2
Value
1
Index
1
Value
2
Index
1
Value
3
Index
1
Value
4
Index
2
Value
5
Index
2
Value
6
This is the dataflow of your program. This probably could be a comment but I needed the visualization to make it more understandable. It is not really clear what you want to do:
For instance, if you enter, in this order:
input==NO_KEY
input!=NO_KEY
input!=NO_KEY
You update the indexes #1 and #2, then the iteration (arduino loop) restarts and you can overwrite the values of the array. Is this what you want?
Also notice that the while loop never gets repeated, this is very clear from the dataflow.
I have rewritten you program to be tested outside of Arduino:
#include "stdio.h"
#define NO_KEY 'a'
int main(){
while(1){
char arr[3];
for (int i = 0; i<3; i++){
char input;
printf("%d -> ", i);
scanf(" %c",&input);
if (input != NO_KEY){
do{
arr[i] = input;
} while(input == NO_KEY );
}
}
for (int i = 0; i <3; i++){ printf("Value %d\n",arr[i]); }
printf("\n Reset\n");
}
}
And this is the output, as expected from your code
0 -> a
1 -> b
2 -> c
Value 127
Value 98
Value 99
Reset
0 -> b
1 -> a
2 -> a
Value 98
Value 98
Value 99

I'm not sure why my nested while loop is stopping after the first iteration

I have to write a C program that asks the user to input a string and it returns how many times each letter of the alphabet occurs in the string (ie. a appears 3 times).
for example, if the user inputs the following string:
Hello
it is supposed to return the following
a or A appears 0 times
b or B appears 0 times
c or C appears 0 times
d or D appears 0 times
e or E appears 1 times
(it does this for the whole alphabet)
Code:
#include<stdio.h>
#include<stdlib.h>
#define MAX 1000
int main(){
char str[MAX];
int count[26]={0};
printf("Enter your string \n");
fgets(str,sizeof(str),stdin);
char str1[]="abcdefghijklmnopqrstuvwxyz";
char str2[]="ABCDEFGHIJKLMNOPQRSTUVWXYZ";
int i=0;
int j=0;
while(i<26){
while(str[j]!='\0'){
if(str[j]==str1[i]||str[j]==str2[i]){
count[i]++;
}
j++;
}
printf("Letter %c or %c appears %d times\n",str1[i],str2[i],count[i]);
i++;
}
return 0;
}
with what I have now it scans for a and then stops after that and just returns zero for every other letter
After the inner while loop
while(str[j]!='\0'){
if(str[j]==str1[i]||str[j]==str2[i]){
count[i]++;
}
j++;
}
j becomes equal to strlen( str ) and str[j] is equal to '\0' So in the next iteration of the outer while loop the inner while loop has a condition equal to logical false. You need at least to reset the variable j to zero before the inner loop.
j = 0;
while(str[j]!='\0'){
if(str[j]==str1[i]||str[j]==str2[i]){
count[i]++;
}
j++;
}
The reason of this logical error is that the variable j is not declared in the scope where it is used. Try to declare variables in minimal scopes where they are used.
Instead of the inner while loop it would be better to write a for loop like
for ( size_t j = 0; str[j] != '\0'; j++ )
{
//...
}

Program won't store characters in 2d array in c

I am creating a program where I insert a number of sentences and the program outputs them in order. I have finished the program, but when I run it it seems like the characters I input into the array aren't displayed or stored correctly, getting as a result random letters instead of the full sentence. Here is the code of the program:
char ch;
int i,j,k;
int nothing = 0;
int count = 1;
char lines[5][256];
int length[256];
int main() {
printf("Please insert up to a max of 5 lines of text (Press enter to go to next line and twice enter to stop the program):\n");
i = 0;
while (i<5){
j = 0;
ch = getche();
if (ch == '\r'){
if(i!= 0){
break;
}
printf("You have not inserted anything, please insert a line:");
i=-1;
}
if(ch != '\r'){
lines[i][j]=ch;
while (ch!='\r'){
ch = getche();
lines[i][j] = ch;
j++;
}
}
printf("\n");
i++;
}
for (k=i ; k > 0; k--){
printf("\tphrase %i :", count);
for ( j =0 ; j <= length[k]; j++){
printf("%c",lines[j][k]);
}
count++;
printf("\n");
}
return 0;
}
How can I get the characters to be stored and displayed correctly? Any help is appreciated, thank you!!
There are numerous problems with your code. I'll try and summarise here, and give you improved code.
Fist, some changes that I made to get this to compile on my system:
Changed getche() to getchar() (getche() does not appear to be available on Ubuntu).
I took out the section about re-entering a string, and just focused on the rest (since the logic there was slightly broken, and not relevant to your question). It will still check for at least one line though, before it will continue.
I had to change the check for \r to \n.
I changed your length array to size 5, since you'll only have the lengths of maximum 5 strings (not 256).
Some problems in your code:
You never updated the length[] array in the main while loop, so the program never knew how many characters to print.
Arrays are zero indexed, so your final printing loops would have skipped characters. I changed the for parameters to start at zero, and work up to k < i, since you update i after your last character in the previous loop. The same with j.
Your reference to the array in the printing loop was the wrong way around (so you would've printed from random areas in memory). Changed lines[j][k] to lines[k][j].
No need for a separate count variable - just use k. Removed count.
The nothing variable does not get used - removed it.
#include <stdlib.h>
#include <stdio.h>
char ch;
int i,j,k;
char lines[5][256];
int length[5];
int main()
{
printf("Please insert up to a max of 5 lines of text (Press enter to go to the next line and twice enter to stop the program):\n");
i = 0;
while (i<5)
{
j = 0;
ch = getchar();
if ((ch == '\n') && (j == 0) && (i > 0))
{
break;
}
if (ch != '\n')
{
while (ch != '\n')
{
lines[i][j] = ch;
j++;
ch = getchar();
}
}
length[i] = j;
printf("\n");
i++;
}
for (k = 0; k < i; k++)
{
printf("\tPhrase %i : ", k);
for (j = 0; j < length[k]; j++)
{
printf("%c", lines[k][j]);
}
printf("\n");
}
return 0;
}

C - exit for loop by pressing enter key

I'm trying to print a string of chars from an array and end the loop whenever I press the "Enter" key.
int i;
char charArry[MAXARY];
printf("Input an array of chars: \n\n");
for (i = 0; i < MAXARY && charArry[i] != 13; i++)
{
scanf(" %c", &charArry[i]);
}
for (i = 0; i < MAXARY; i++)
{
printf(" %c", charArry[i]);
}
For some reason whenever I press the Enter key it just goes to a new line instead of breaking the loop. Any suggestions?
P.S
MAXARY is a constant for the array length, currently 20.
Your close to having this working. Whilst I agree the use of scanf should be avoided, see: Why does everyone say not to use scanf? What should I use instead?, the reason your program doesn't do what you expect is due to a logic error.
Your for loop states:
for (i = 0; i < MAXARY && charArry[i] != 13; i++)
Now recapping how a for loop works, you have:
1. initalization (i=0)
2. conditional check (i < MAXARY && charArry[i] != 13)
3. conditional block (scanf)
4. increment (i++)
5. return to 2
You'll note your charArray[i] != 13check is happening after i has been incremented. Hence your not checking against the character you just read but the next character in charArray[i]. This is why your never breaking your loop at the \r character.
A recommended fix would be:
for (i = 0; i < MAXARY; i++)
{
int result = scanf("%c", &charArry[i]);
if( result != 1 || charArry[i] == '\n' )
break;
}
Which checks scanf was successful and charArry when i is the character that was read.
Also note as chux has pointed out the \r character is a carrage return, not the newline. Hence this check will only work if your working on windows (as unix doesn't use \r). If you want to be platform independant use \n
For some reason whenever I press the Enter key it just goes to a new line instead of breaking the loop.
The space in the format scanf(" %c", &charArry[i]); directs scanf() to consume and discard all optional leading white-space. charArry[i] will never be assigned 13 as 13 is typically '\r', a white-space.
An enter key is usually translated to '\n'.
Do not test values that have not been assigned #Red Alert
// v---------v not assigned yet.
for (i = 0; i < MAXARY && charArry[i] != 13
Repaired code
int i;
char charArry[MAXARY];
printf("Input an array of chars: \n\n");
for (i = 0; i < MAXARY; i++) {
if (scanf("%c", &charArry[i]) != 1) break; // End of file or error occurred
// If enter key encountered
// Usualy the charArry[i] == '\r' is not needed.
if (charArry[i] == '\n' || charArry[i] == '\r') break;
}
// Only print out characters that were read.
int j;
for (j = 0; j < i; j++) {
printf("%c", charArry[j]);
}

Scanf and two strings

My task is read two strings of digits and save them in different arrays.
I decided to use scanf function, but program can read only first string.
This is my bad-code.
int main()
{
int firstArray[50], secondArray[50], i, j;
/* fill an array with 0 */
for(i=0; i<50; ++i)
{
firstArray[i]=secondArray[i]=0;
}
i=j=0;
while((scanf("%d", &firstArray[i]))== 1) { ++i; }
while((scanf("%d", &secondArray[j]))== 1) { ++j; }
/* Print this. */
for(i = 0; i < 20; ++i)
{
printf("%d ", firstArray[i]);
}
putchar('\n');
for(j = 0; j < 20; ++j)
{
printf("%d ", secondArray[j]);
}
return 0;
}
I just don't understand how scanf function works. Can someone please explain?
scanf ignores blank characters (including new line). Thus your scan will read entire input into firstArray if you have no "non blank" separator.
If file/data has ; at end of first line it will stop the read into firstArray there, and never read anything into secondArray - as you never consume the ;.
/* This will never be 1 as ; is blocking */
while((scanf("%d", &secondArray[i])) == 1) {
So: if you separate with i.e. ; you will have to read / check for this before you read into secondArray.
You could also add something like:
char c;
/* this can be done more tidy, but only as concept */
while((scanf("%d", &firstArray[i])) == 1 && i < max) {
++i;
if ((c = getchar()) == '\n' || c == ';')
break;
}
Also instead of initializing array to 0 by loop you can say:
int firstArray[50] = {0}; /* This set every item to 0 */
Also take notice to ensure you do not go over your 50 limit.
You say strings of digits and you read %d. The format scans the input for the longest sequence representing an integer (signed) value. Two "digit strings" are consumed by the first while loop.
EDIT Instead of "strings of digits" you should say "strings of integers". In this case it is a little bit more subtle since the first while can consume all the integers, unless they are separated by something that is not a possible integer (e.g. a ;).
So, to make the following to work, you must separate the two "lines" with something that can't be parsed as integer and which is not considered "white character". Not the better solution, but one the possible.
#include <stdio.h>
#include <ctype.h>
int main()
{
int firstArray[50] = {0};
int secondArray[50] = {0};
int i, j, l1, l2;
int tmp;
i = j = 0;
// read integers, but not more than size of array
while( scanf("%d", &firstArray[i]) == 1 && i < sizeof(firstArray) ) {
++i;
}
// consume non digits
for(tmp = getchar(); tmp != EOF && !isdigit(tmp); tmp = getchar());
// on EOF you should exit and stop processing;
// we read one more char, push it back if it was a digit
if (isdigit(tmp)) ungetc(tmp, stdin);
while( scanf("%d", &secondArray[j]) == 1 && j < sizeof(secondArray) ) {
++j;
}
l1 = i; // preserve how many ints were read
l2 = j;
/* Print this. */
for(i = 0; i < l1; ++i)
{
printf("%d ", firstArray[i]);
}
putchar('\n');
for(j=0; j < l2; ++j)
{
printf("%d ", secondArray[j]);
}
return 0;
}
EDIT A solution that maybe fits your need better is to read the lines (one per time) into a buffer and sscanf the buffer.
You cannot use scanf to do that.
Read the documentation.
Observations:
with scanf if you enter a digit your loop runs forever
there is no check on size 50 limit of your arrays
if you press return then it ignores that line because does not match your pattern
if you enter a letter the pattern does not match and loop breaks
So use some other function, maybe gets, atoi or strtol. And remember to check the size 50 limit of your arrays.
Actually, there is one special point in C's arrays.
Though you declare an array's size. say int arr[5]; You can store values beyond the size of 5. It doesn't show any error but leads to undefined behavior (Might overwrite other variables).
Please Refer this question: Array size less than the no. of elements stored in it
In you case, that was your problem. The compiler had never passed beyond the first while statements. Thus, you didn't get any output. In fact, it didn't even compile the whole code yet!
while((scanf("%d", &firstArray[i]))== 1) { ++i; }
So, you could write this while statement like this:
while( scanf("%d", &firstArray[i]) ==1 && i<50 )
i++;
or else:
while(i<50 )
{
scanf("%d", &firstArray[i]);
i++;
}
or else:
for (i=0; i<50; i++)
scanf("%d", &firstArray[i]);

Resources