word entry in an array of strings - c

I'm trying to make a program that will read up to 20 words entered by the user and stored in an array of strings. The program will ask for additional words until 20 words have been entered or until the word 'done' has been entered. The idea is that these words will then be entered into a matrix to create a word search program. I'm stuck on scanning in the words entered by the user. I'm a new programmer so any words of advice is very beneficial.
#include <stdio.h>
int main(void)
{
char string[20][100];
printf("Enter up to 20 words to hide in the puzzle.\n");
printf("Enter the word 'done' after your last word if entering less than 20 words.\n");
scanf("%s\n",c)
printf("Entered words:\n");
return 0;
}

#include<stdio.h>
#include<string.h>
int main(void)
{
char words[20][100];
char temp[100]="\0";
int i=0;
int end=0; //0 false and 1 true
printf("Enter 20 words or enter done to exit.\n");
while(i <=19 && end==0)
{
strset(temp,'\0');// resets array temp to NULL's everytime
scanf(" %99[^\n]",temp); //this is scan set, to read a string without '\n'
printf("Given:%s\n\n",temp);
if(strcmpi(temp,"done")==0)//compares given input with "done".if "done" is entered. zero is returned
end=1;//when 0 is returned this end=1 will break the loop.
else//if input is not given "done" then copy temp array to words[i].
{
strcpy(words[i],temp);
i++;
}
}
}
Instead of using words[20][100] directly, I have used a temporary array named temp to initially store the input,because at the end i don't want to store "done" into words[20][100].Assuming that "done" is used only to end the input process and it is not the actual word to store.But you can change this program to your need.

This is a straight-forward but bug-fixed variant of the code provided by developer3466402 in his answer.
I've used a for loop instead of a while loop since that neatly summarizes the action in the while loop. I added n to record how many words were entered, leaving i as a loop control variable (yes, once upon a long time ago I wrote Fortran too).
#include <stdio.h>
#include <string.h>
int main(void)
{
char words[20][100];
int i = 0;
int n;
printf("Enter up to 20 words to hide in the puzzle.\n");
printf("Enter the word 'done' after your last word if entering less than 20 words.\n");
for (i = 0; i < 20; i++)
{
printf("Enter word %2d:\n", i+1);
if (scanf("%99s", words[i]) != 1 || strcmp(words[i], "done") == 0)
break;
}
n = i;
printf("%d words entered\n", n);
for (i = 0; i < n; i++)
printf("Word %2d = [%s]\n", i+1, words[i]);
return 0;
}
It worked OK for me entering 0, 1, many and 20 words. We can debate the newline after the prompt; it has pros and cons, but that's generally true. I chose to echo the data after the loop rather than within the loop. Be aware that with some programs, echoing in a loop can appear to work where echoing after the loop shows a problem.
Example run (with an early exit):
$ ./rw
Enter up to 20 words to hide in the puzzle.
Enter the word 'done' after your last word if entering less than 20 words.
Enter word 1:
aleph
Enter word 2:
null
Enter word 3:
absolute
Enter word 4:
twaddle and nonsense
Enter word 5:
Enter word 6:
Enter word 7:
elephants are done for
Enter word 8:
Enter word 9:
8 words entered
Word 1 = [aleph]
Word 2 = [null]
Word 3 = [absolute]
Word 4 = [twaddle]
Word 5 = [and]
Word 6 = [nonsense]
Word 7 = [elephants]
Word 8 = [are]
$

You can dynamically allocate memory to store words. If the user inputs more than 20 words, then you can use realloc function to allocate more memory.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void) {
int wlimit = 20;
int wcount = 0;
int retval; // to save the return value of scanf
char wstring[100+1]; // +1 for the terminating null byte
char **wlist = malloc(wlimit * sizeof *wlist);
if(wlist == NULL) {
// handle it
printf("not enough memory to allocate\n");
return 1;
}
char *temp;
while(1) {
if(wcount >= wlimit) {
wlimit *= 2;
temp = wlist;
wlist = realloc(wlist, wlimit);
if(temp == NULL) {
printf("not enough memory to allocate\n");
wlist = temp;
}
}
retval = scanf("%100s", wstring);
// if the input string is done, then break out of the
// loop else keep taking input from the user
if(retval != 1 || strcmp(wstring, "done") == 0)
break;
// strdup function creates a new string which is a duplicate
// of the input string and returns a pointer to it which can
// be freed using free
wlist[wcount++] = strdup(wstring);
}
// do stuff with wlist
// after done, free the memory
for(int i = 0; i < wcount; i++)
free(wlist[i]);
free(wlist);
wlist = NULL;
// stuff
return 0;
}

I think you wish something like below:
#include<stdio.h>
int main(void)
{
char words[20][100];
int i = 0;
printf("Enter up to 20 words to hide in the puzzle.\n");
printf("Enter the word 'done' after your last word if entering less than 20 words.\n");
while (i < 20) {
printf("Entered words:\n");
if (scanf("%99s", words[i]) != 1 || strcmp(words[i], "done") == 0)
break;
printf("%s\n", words[i]);
i++;
}
return 0;
}

Related

resolving memory loss between two arrays in C

Good evening. I'm working on a program for class and I am hitting a brick wall when it comes to dealing with arrays using C.
--EDIT-- Full code has been posted.
#define _CRT_SECURE_NO_WARNINGS
#define STRMAX 20
#define MAX 100
#include<stdio.h>
int main()
{
int count = 0;
char strlist[STRMAX][MAX];
int start = 0, end = STRMAX;
for (start; start < end; start++) {
char string[MAX];
printf("Enter a string: ");
fgets(string, MAX - 1, stdin);
printf("\nThe string is: %s", string);
int size = strlen(string);
int result = strcmp(string, "stop\n");
if (result == 0) {
break;
}
strcpy(strlist[start], string);
count = count + 1;
}
char rev[STRMAX][MAX];
int temp = 0;
printf("count is: %d\n",count);
while (count != 0) {
strcpy(rev[temp], strlist[count]);
temp = temp + 1;
count = count - 1;
}
printf(rev);
return 0;
}
The last line, printf(rev); is throwing the warning: "using uninitialized memory 'rev'. "
I do not understand C, its the beginning of this course. However I am NOT looking for a "do my homework for me" answer, more of a "here is a better way to go about this" answer.
the output for the code is:
Enter a string: 1
The string is: 1
Enter a string: 2
The string is: 2
Enter a string: 3
The string is: 3
Enter a string: stop
The string is: stop
count is: 3
╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠3
the "count is: 3" is entirely for debugging. I really don't have a clue why my solution doesn't work. If there is any more information that is needed or anything else you would like to see feel free to ask and i'll update the post! thanks.
--EDIT--
STRMAX and MAX are both definitions set for the 2D array required for keeping an array of strings (20 and 50 respectively)
First of all, the line
strcpy(rev[temp], strlist[count]);
is wrong. Valid indexes for strlist are 0 to count-1, assuming that you only want to read valid strings. However, you are using the indexes 1 to count instead. Therefore, you should move the line
count = count - 1;
before that line.
Also, the line
printf(rev);
does not make sense.
If you want to print all strings in the array, then you should print every string individually, in a loop.
Since you are storing the number of valid strings in the variable temp, you must print that many strings.
for ( int i = 0; i < temp; i++ )
{
printf( "%s\n", rev[i] );
}
Also, you should #include <string.h>, because you are using strcpy and strlen.
Additionally, you probably should remove the trailing newline character from the input obtained from fgets. Otherwise, you will be printing that newline character, which will give you unwanted extra lines, forcing you to compensate by printing less newline characters explicitly. The existance of the newline character is also forcing you to add a newline character to the target string "stop":
int result = strcmp(string, "stop\n");
You will be able to remove that newline character from the target string if you also remove it from the input string.
After making these changes, your code should look like this:
#define _CRT_SECURE_NO_WARNINGS
#define STRMAX 20
#define MAX 100
#include <stdio.h>
#include <string.h>
int main()
{
int count = 0;
char strlist[STRMAX][MAX];
int start = 0, end = STRMAX;
for (; start < end; start++) {
char string[MAX];
printf("Enter a string: ");
fgets(string, MAX - 1, stdin);
//remove trailing newline character
string[strcspn(string,"\n")] = '\0';
printf("The string is: %s\n", string);
int result = strcmp(string, "stop");
if (result == 0) {
break;
}
strcpy(strlist[start], string);
count = count + 1;
}
char rev[STRMAX][MAX];
int temp = 0;
printf("count is: %d\n",count);
while (count != 0) {
count = count - 1;
strcpy(rev[temp], strlist[count]);
temp = temp + 1;
}
for ( int i = 0; i < temp; i++ )
{
printf( "%s\n", rev[i] );
}
return 0;
}
This program has the following output:
Enter a string: 1
The string is: 1
Enter a string: 2
The string is: 2
Enter a string: 3
The string is: 3
Enter a string: stop
The string is: stop
count is: 3
3
2
1

How to limit input length with scanf

In this program I have taken a dimensional character array of size[3][4],
as long as I enter a 3 characters for each row it will work well.
For example: if I enter abc abd abd I get the same output but if i enter more letters in the first or second or 3rd row I get an error.
How should I check for null character in 2 dimensional?
# include <stdio.h>
#include <conio.h>
# include <ctype.h>
void main()
{
int i=0;
char name[3][4];
printf("\n enter the names \n");
for(i=0;i<3;i++)
{
scanf( "%s",name[i]);
}
printf( "you entered these names\n");
for(i=0;i<3;i++)
{
printf( "%s\n",name[i]);
}
getch();
}
As pointed out by #SouravGhosh, you can limit your scanf with "%3s", but the problem is still there if you don't flush stdin on each iteration.
You can do this:
printf("\n enter the names \n");
for(i = 0; i < 3; i++) {
int c;
scanf("%3s", name[i]);
while ((c = fgetc(stdin)) != '\n' && c != EOF); /* Flush stdin */
}
How should I chk for null character in 2 dimensional ... [something has eaten the rest part, I guess]
You don't need to, at least not in current context.
The problem is in your approach of allocating memory and putting input into it. Your code has
char name[3][4];
if you enter more that three chars, you'll be overwriting the boundary of allocated memory [considering the space of \0]. You've to limit your scanf() using
scanf("%3s",name[i]);
Note:
change void main() to int main(). add a return 0 at the end.
always check the return value of scanf() to ensure proper input.
EDIT:
As for the logical part, you need to eat up the remainings of the input words to start scanning from the beginning of the next word.
Check the below code [Under Linux, so removed conio.h and getch()]
# include <stdio.h>
# include <ctype.h>
int main()
{
int i=0; char name[3][4];
int c = 0;
printf("\n enter the names \n");
for(i=0;i < 3;i++)
{
scanf( "%3s",name[i]);
while(1) // loop to eat up the rest of unwanted input
{ // upto a ' ' or `\n` or `EOF`, whichever is earlier
c = getchar();
if (c == ' ' || c == '\n' || c == EOF) break;
}
}
printf( "you entered these names\n");
for(i=0;i<3;i++)
{
printf( "%s\n",name[i]);
}
return 0;
}
(Cringing after reading the answers to date.)
First, state the problem clearly. You want to read a line from stdin, and extract three short whitespace separated strings. The stored strings are NUL terminated and at most three characters (excluding the NUL).
#include <stdio.h>
void main(int, char**) {
char name[3][4];
printf("\n enter the names \n");
{
// Read tbe line of input text.
char line[80];
if (0 == fgets(line, sizeof(line), stdin)) {
printf("Nothing read!\n");
return 1;
}
int n_line = strlen(line);
if ('\n' != line[n_line - 1]) {
printf("Input too long!\n");
return 2;
}
// Parse out the three values.
int v = sscanf(line, "%3s %3s %3s", name[0], name[1], name[2]);
if (3 != v) {
printf("Too few values!\n");
return 3;
}
}
// We now have the three values, with errors checked.
printf("you entered these names\n%s\n%s\n%s\n",
name[0], name[1], name[2]
);
return 0;
}
you might consider something on the order of scanf( "%3s%*s",name[i]);
which should, if I recall correctly, take the first three characters (up to a whitespace) into name, and then ignore anything else up to the next white space. This will cover your long entries and it does not care what the white space is.
This is not a perfect answer as it will probably eat the middle entry of A B C if single or double character entries are mode. strtok, will separate a line into useful bits and you can then take substrings of the bits into your name[] fields.
Perhaps figuring out the entire requirement before writing code would be the first step in the process.

Check if input is a string (4 characters only) and if not return to input again

My aim is to accept 4-digit numbers, and 4-character strings (string should not contain digits or special characters)
If an invalid input is given the program should not terminate and it must allow the user to enter the details and continue until he wish to terminate.
I am able to find whether the input is a digit.
if(scanf("%d",&input)!=1)
{
printf("enter the number please");
... // I have option to re enter using while and flags
}
else
{
// I continue my work
...
}
To check it is four digits I have tried using the commands
i=0;
num = input;
while(num>0)
{
i = i+1;
num = num/10;
}
if(i==4){
...//I continue
}
else
printf("please enter four digit");
I have no idea of checking the same for characters. (I know how to check its length using strlen())
Please help me with the code in C. (Also help me to reduce/optimize the above logic to check whether the input is a 4-digit number)
I believe you want 2 inputs a number and a string. You can do that as
int number= 0;
char string[10] = { 0 };
do {
printf("please enter four digit");
scanf("%d", &number);
if(number >=1000 && number<= 9999)
break;
} while(1);
do {
printf("please enter four character string");
fgets(string, sizeof(string), stdin);
if(strlen(string) == 4)
break;
} while(1);
To check it is four digit number you can simply put a check whether the number lies between 1000 and 9999. (I am assuming you don't want the number to start with 0.)
strtol can help:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
char s[32], *p;
int x;
fgets(s, sizeof(s), stdin);
if ((p = strchr(s, '\n')) != NULL)
*p = '\0';
x = (int)strtol(s, &p, 10);
if ((p - s) == 4) {
printf("%d\n", x);
} else {
printf("Please enter four digit\n");
}
return 0;
}
char input[16];
int ok = 1, k = 0;
if (scanf("%s", input) > 0 && strlen(input) == 4) {
// check if it's a word
for (; k < 4; k++)
if (!isalpha(input[k])) {
// check if it's a number
for (int k = 0; k < 4; k++)
if (!isdigit(input[k]))
ok = 0;
break;
}
}
else ok = 0;
if (!ok)
printf("invalid input, please enter a 4-digit number or 4-letter word");
else {
printf("valid input");
...
}
You can use gets()1 fgets() to get the whole line and check line length. If the first character is between '0' and '9' then check the remaining if they are 3 numbers too. If the first character is a valid character in string then check the 3 remaining chars if it's also valid in string.
1See Why is the gets function so dangerous that it should not be used?

trying to run two parts of program second part can't input string

I am trying to get both parts of this program to work as you can see I have split it with first part (question 1) and second part (question 2). The problem is first part runs fine just when the second part starts I can not input any string and it just seems to skip through the code without letting me input the string.
If I delete the first part (question 1) of the program then everything works fine and I can input the string. What interrance is causing this issue.
int main()
{
first();
second();
}
//Question 1
int first()
{
/* dataarray.c */
float data[20] = {
50.972438, 93.765053, 9.252207, 1.851414, 16.717533,
71.583113, 97.377304, 20.352015, 56.309875, 0.072826,
23.986237, 36.685959, 80.911919, 86.621851, 53.453706,
96.443735, 29.845786, 18.119300, 31.079443, 52.197715 };
/* The number of elements in the data array */
int data_size = 20;
int pos;
int j;
int i;
int k;
printf("Question 1\n");
for(i=0;i<data_size;i++)
{
printf("\nArray %i is %f ",i,data[i]); //Initial arrays print statement
}
printf("\n\nArray number to delete:"); //User Choose one to delete
scanf("%i",&pos);
k =0;
for(j = 0; j< pos;j++)
{
printf("\n Array %i is now %f ",k,data[j]);
k++;
}
k=pos;
for(j=pos+1;j<data_size;j++)
{
printf("\n Array %i is now to %f ",k,data[j]); //Shows array changed to
k++;
}
data_size = data_size - 1; //Decreases data size
}
//Question 2
int second()
{
printf("\n\nQuestion 2\n");
int a,b,check=0;
char str[20];
printf("\nEnter a String:\n"); //User inputs word to check if its palindrome
gets(str);
for(b=0;str[b]!=0;b++); //Starts at 0 increment till the last length
b=b-1;
a=0;
while(a<=b)
{
if(str[a]==str[b]) //String a is forwards b is backwards
{
a=a+1;
b=b-1;
check=1; //If check = 1 then a palindrome
}
else
{
check=0; //If check = 0 then it not a plaindrome
break; //Loop break
}
}
if(check==1)
printf("It is a Palindrome:"); //Statement printed if check = 1
else
printf("It is not a Palindrome\n"); // Else if 0 this statement is printed
}
When you call scanf in part one, I presume you enter a number followed by a newline. scanf consumes the number, but the newline is left in the buffer. The gets() in part 2 then sees the newline and returns a blank line. An easy solution is to do
scanf( "%i\n", &pos );
BTW, never use gets. Use fgets instead.

Program to show the number of characters in a string

This is a program to find the number of characters in a string. But it counts the wrong number of characters. Is it counting the white space too ? Even if that is true how can the total number be 89 ? (see output below)
#include <stdio.h>
#include <conio.h>
void occurrence(char str[100], char ch)
{
int count=0,max =0,i;
for(i=0;i<=100;i++)
{
if(str[i]!='\0')
{
max = max + 1;
if(str[i]==ch)
{
count = count + 1;
}
}
}
printf("\nTotal Number of characters : %d\n",max);
printf("\nNumber of Occurrences of %c : %d\n",ch,count);
}
int main(void)
{
void occurrence(char [], char);
int chk;
char str[100], ch, buffer;
clrscr();
printf("Enter a string : \n");
gets(str);
printf("Do you want to find the number of occurences \nof a particular character (Y = 1 / N = 0) ? ");
scanf("%d", &chk);
do
{
if (chk==1)
{
buffer = getchar(); //dummy varaiable to catch input \n
printf("Enter a Character : ");
ch = getchar();
occurrence(str,ch);
printf("\n\nDo you want to check the number of occurences \nof another character (Y = 1 / N = 0) ? ");
scanf("%d", &chk);
}
else
{
exit();
}
}
while(chk);
return 0;
}
There are two important things wrong with the for loop that counts characters:
It goes from 0 to 100, when it should go from 0 to 99. If you allocate a 100-element array, then the index of the highest element is 99, for a total of a hundred elements. Traditionally the exit condition for the loop would be i < 100, not i <= 100.
It keeps going after the '\0' is found. The '\0' character marks the end of the string, and you should not count any characters after it. Some of the characters after the '\0' may themselves be '\0's, and so you won't count them; but there could be any other kind of garbage there as well, and those will mess up your count. You must figure out how to change your for loop to exit as soon as the '\0' character is found, and not count anything else after that point.
Yes, whitespace is a character. Also are characters each of the 100 elements in your array. You are counting everything but nulls, sp I guess you have 11 nulls. Also, your for loop is off by one.
This will give you correct output.
void occurrence(char str[100], char ch)
{
int count=0,max = 0,i = 0;
while(str[i]!='\0')
{
max = max + 1;
if( str[i] == ch )
{
count = count + 1;
}
i++;
}
}

Resources