C Program calling array containing strings within a loop - c

I am fairly new to C, and am having problems with my array.
The application is an anagram game, and should compare the users guess to the correct word.
I am trying to log all of the incorrect answers, as well as the correct versions of the answers in two seperate arrays.
However, at the end of the program when I try and print all of the incorrect guesses and correct versions, it only prints the first term in the array.
I think it may be a problem caused by the arrays, as they are holding strings, so in C it is essentially an array within an array I think?
Why does my code just print the first term from the arrays?
(There is more code, however this is just the key part, I think this is the only section that needs looking at)
char correctWord[20];
char anagramWord[20];
int guesses, score;
char* incorrectGuess[20];
char* correctVersion[20];
void userGuess(){
char userWordGuess[20];
printf("Anagram: ");
printf(anagramWord);
printf("\n Your Guess: ");
scanf("%s",userWordGuess); //Reads in user input
strtok(correctWord, "\n");
guesses++;
if(strcmp(userWordGuess, correctWord) == 0){
printf("Congratulations, you guessed correctly! (Please wait for the
next question...)\n");
score++;
Sleep(1600);
system("cls");
}else{
printf("Incorrect, try harder!(Please wait for the next question...) \n");
Sleep(1600);
system("cls");
int i = 0;
incorrectGuess[i]=(userWordGuess);
correctVersion[i]=(correctWord);
i++;
}
}
void finalScore(){
int i;
system("cls");
int percentage = ((score/guesses) * 100);
printf("Congratulations - Game Complete!");
printf("\n Guesses: %d", guesses);
printf("\n Score: %d", score);
printf("\n Percentage Correct: %d", percentage);
int numberOfIncorrect = (guesses-score);
for(i=0;i<=numberOfIncorrect;i++){
printf(incorrectGuess[i]);
printf(correctVersion[i]);
}
getch();
}

In this code, you are not initializing guesses and score with any values, and you try to increment them. You should have
int guesses = 0 , score = 0 ;
and then, in your else block
else
{
printf("Incorrect, try harder!(Please wait for the next question...) \n");
Sleep(1600);
system("cls");
int i = 0; // you initialize i to 0 every time
incorrectGuess[i]=(userWordGuess);
correctVersion[i]=(correctWord);
i++;
}
in the commented line, you initialize i to 0 each time.

At first, variables guesses and score doesn't init. You need something like
int guesses=0, score=0;
And in this lines
incorrectGuess[i]=(userWordGuess);
correctVersion[i]=(correctWord);
you do not copy the string. You should use
incorrectGuess[i]=strdup(userWordGuess);
correctVersion[i]=strdup(correctWord);
instead. Or you could use malloc and strcpy like this
incorrectGuess[i] = malloc(strlen(userWordGuess)+1);
strcpy(incorrectGuess[i], userWordGuess);
correctVersion[i] = malloc(strlen(correctWord)+1);
strcpy(correctVersion[i], correctWord);
In this cases, at the end you need to free the allocated memory like
free(incorrectGuess[i]);
free(correctVersion[i]);

This:
incorrectGuess[i]=(userWordGuess);
is wrong, the string is not copied. All you're doing is storing a pointer to the array holding the current guess, and that array's the same all the time.
You need to copy the actual characters into newly allocated memory to remember them. You can also make it a 2D-array:
char incorrectGuess[20][100];
and just strcpy() the current guess in there. Beware so you don't overwrite, use snprintf() if you have it.

Related

How to increment and decrement a char pointer in a menu-driven C program?

This is obviously a school assignment. However, with few people to ask for help due to the Corona-outbreak I am reaching out to you for help as am novice and have tried for hours. There is obviously something key with pointers that I am missing.
So, the challenge is to write a program that is letting the user manipulate a pointer through a menu. The pointer should print what it points to after each choice has been made. To start off, the pointer is pointing at the first character of the string e.g. "W" (Washington), and if choice 1 is made by the user the pointer should point at "a" etc. A classic switch case scenario.
It is not allowed for the pointer to point out of the allocated memory.
The code below is not working properly. When I execute the program and choose alternative 1 it says "Dereference of out-of-bounds pointer: 1 bytes past end of array". I need help to interpret this, an explanation of what I might have missed and ideally a few comments for improvements.
Thank you!
#include <stdio.h>
int main (void){
int count, option;
char text[10] = "Washington";
char *my_pointer = text; /* Pointer which points to the beginning of text (string) */
count = 0;
/* Letting the user manipulate the pointer through the menu. The pointer should print what it points to. */
do{
printf("The text string is: %s\n\n", text);
printf("The pointer points to %c choose an operation:\n", *my_pointer);
printf("MENU\n");
printf("1. Plus 1\n"); /* Increment the pointer - one step to the left */
printf("2. Minus 1\n"); /* Decrement the pointer - one step to the right */
printf("3. End Program\n");
scanf("%d", &option);
switch(option){
case 1:
while(count < 10)
{
my_pointer++;
count++;
}
break;
case 2:
while(count < 10)
{
my_pointer--;
count--;
}
break;
case 3:
printf("Program Ends");
break;
default:printf("\n Wrong input, choose 1 - 4.\n");
}
}while (option != 3);
return 0;
}ยดยดยด
Misc bugs:
In case 2 you need to check the lower bound (zero) not the upper bound (10).
The while loops inside case 1 and 2 should be if statements.
You seem to print the character when it is pointing at offset + 10 which is 1 beyond the end of the array.
char text[10] = "Washington"; doesn't allocate room for null termination, see How should character arrays be used as strings?

Abort trap when storing users input into two arrays

I am going to take in a users input consisting of their identification and their mark, separated by a space. The code compiles and I can enter answers at the prompt, however, at the end of the prompts (end of the first loop) I get an "Abort trap: 6" appearing.
I would appreciate it if you could help me find out why this comment is arising. I read that it could be from me overwriting over other memory, but it looks like my loops do not go beyond what I would want them to loop over (user gives me 10 answers).
I also added ampersands in front of the arrays in scanf, which I found odd to do, but the code did not compile otherwise.
include
int main (void){
char id[10];
int mark[10];
for (int i=0;i<10;i++){
printf("Enter ID and mark: \n");
scanf(" %s %d", &id[i], &mark[i]);
}
for (int i=0;i<10;i++){
printf("%c ",id[i]);
}
}
I think your ID reading is wrong, your IDs are string of 7 character length while your char id[10] is a string of 10 char ( where you intended to use a list of string ), you should use char *ids[10] instead.
char *ids[10] = { NULL }; // list of 10 string, initialized to NULL
int mark[10];
for (int i=0;i<10;i++){
...
char* id=malloc(8*sizeof(char)); // allocate a new string to store
scanf( "%7s %d\n", id, &mark[i] ); // check the result of the scanf to ensure you got the correct input
ids[i] = id; // store the string at position in the list
}
for (int i=0;i<10;i++){
printf("%s\n", ids[i]);
}
Also using a debugger like GDB would help you pinpoint where is the error happening in your code. And probably help you figure out your mistake.

Variable value is reset inside a loop in C

I have a case in which I have to identify if a number is positive, negative or zero and count how many times each of these cases happen. The code I wrote is this:
#include
#include
#include
using namespace std;
int main(int argc, char *argv[])
{
char opcion = 's';
int positivos = 0;
int negativos = 0;
int ceros = 0;
//int ceros2 = 0;
int temporal;
do{
printf("Enter a number: ");
scanf("%d",&temporal);
if(temporal >= 0)
{
if(temporal==0)
{
ceros ++;
}
else
{
positivos ++;
}
}
if(temporal < 0)
{
negativos ++;
}
printf("Do you want to enter another number? (s/n)");
scanf("%s",&opcion);
}
while(opcion == 's' || opcion=='S');
printf("you have %d possitive numbers \n",positivos);
printf("you have %d negative numbers \n",negativos);
printf("you have %d zero \n",ceros);
return 0;
}
If I run the code as it is, the number of zeroes will always be zero, but if you uncoment the line 13 int ceros2 = 0; (my logic was "let's declare another initializaed variable and see what happens") then the program will count the zeroes as expected. Why do i have to declare a useless variable in order to the program make the count?
What is C compiler doing with the code that does not respect the value of the last declared and initialized variable unless you declare a new initialized variable?
You are asking scanf() to read in a C string, which, if the user types a character, will contain both that character and the null terminator. You have provided only a single character's worth of storage. So, the null terminator doesn't fit but it gets stored somewhere. As it happens, it's clobbering other data that happens to be next to opcion on the stack and that happens to be your ceros variable.
Declaring another variable has reorganized the layout of data on the stack and changes what gets clobbered, so you're not noticing it. It's still writing out of bounds, though.
You could use a format string of "%c" to read a single character.

I received the error message: Run-Time Check Failure #2. Stack around the variable was corrupted. However, I was not out of bounds of any array

I've been doing some exercise with structures to prepare for my upcoming exams, and I've run into a bit of trouble with this code.
// Creates a structure of type 'person' with a first name (nameF), last name (nameL), and the age (age)
typedef struct {
char nameF[20];
int age;
char nameL[40];
}person;
// Main function
int main() {
person ppl[2]; // We are creating 3 "people", whose information shall be printed into the file
// This loop takes user input to create the names and ages of 3 people
int i;
for (i = 0; i <= 2; i++) {
printf("\nEnter first name %d: ", i+1);
scanf("%s", &ppl[i].nameF);
printf("%s\n", ppl[i].nameF);
}
printf("It worked\n");
system("pause");
return 0;
}
It runs fine, but when the program exits, I keep receiving an error message from the Debugger that states: "Run-Time Check Failure #2. Stack around the variable 'ppl' was corrupted."
So I looked it up on Stack Overflow, this error appears when you go outside the bounds of a string. I don't understand where in my code I'm going out of bounds.
Here's an example of the output:
Enter first name 1: 'Adolfo'
Adolfo
Enter first name 2: 'Cecilia'
Cecilia
Enter first name 3: 'Tim'
Tim
Press any key to continue...
And then the error message pops up.
As you can see none of my inputs exceed the maximum amount of characters for the variable 'nameF', so there should be no reason for me to receive the error.
I saw someone on Stack Overflow mention that instead of making a character array:
char nameF[20];
One should instead write use dynamic memory allocation:
char * nameF = malloc(<enough bites to support any input);
Unfortunately, I don;t quite have a grasp of memory allocation yet, and when I attempted this code, I received all sorts of other errors, and my program wouldn't even run.
What is the mistake?
Also, I am not sure if this information is important, but I wrote this code using Visual Studio in C.
Edit: "char * nameF[20]" to "char nameF[20]" that asterisk was a leftover from my previous attempts at fixing the code, sorry.
Why are you allocating two structures then filling it with three responses?
Also, scanf is very dangerous as it can easily be abused to overwrite past a buffer. Look for routines (or write one) that limits the input to the length of the string.
hint: scanf man page might lead you to a better version.
Not meant as an answer, just made some adaptions allowing you to continue your work:
typedef struct {
char nameF[20]; // may take on 19 characters (+ string terminating char)
int age;
char nameL[40];
}person;
int main() {
person ppl[3]; // 3, not 2.
int i;
for (i = 0; i <= 2; i++) {
printf("\nEnter first name %d: ", i+1);
scanf("%s", ppl[i].nameF); // removed the &
printf("%s\n", ppl[i].nameF);
}
printf("It worked\n");
system("pause");
return 0;
}

C language printing strings from array in a loop

I am making a console application in C using visualstudio 2015 so that a user can enter the amount of sweets they wish to make and the name of the sweet however there is a problem, the problem is that when the program tries to read a string from the array the program crashes and doesnt print out anything, however if I change it to print a single character using %c it will print out the first character of the string for example if I enter 2 sweets and the strings 'Jawbreaker' and 'Lollipop' It will crash if I use %s for the string however if I use %c for a character it will do its job and print 'J' and 'L' respectively on different lines, Any ideas how I could get this working with the %s specifier for the strings?
The code is below:
#include <stdio.h>
/*Declares the variable needed*/
int sweet_number;
char sweet_name[999];
int main(void) {
/*Prompts the user to enter the number of sweets and saves it to sweet_number*/
printf("Please enter the number of sweets:\n");
scanf("%d", &sweet_number);
/*for loop to enter the name of the sweet into the array*/
for (int i = 0; sweet_number > i; i++) {
printf("What is the name of the sweet?\n");
scanf("%s", &sweet_name[i]);
}
/*Prints array to screen*/
for (int j = 0; sweet_number > j; j++){ /* <- This is where code fails to run*/
printf("%s\n", sweet_name[j]);
}
return 0;
}
You have to use an 2-dimensional array. sweet_name is an array(1-D), each index can store at most one character not a string. Change the following line
char sweet_name[999];
to
char sweet_name[999][100];
OK, I would advice you doing something more efficient and that is to use a double pointer. By doing that, you can solve some problems that the 2D array version has.
The first problem is, what do you do if the user wants to insert more than 999 sweets. Your array can't hold them.
Second, what do you do if the user enters a name that is bigger than 100 characterrs. Again, your 2D array can't hold it. And also, although there is the possibility for the user to enter a name bigger than 100 characters, most users will enter much less than this and now for every string, you have allocated 100 positions when you probably only need about 50. So, let's deal with these problems.
I would probably do something like this:
#include <stdio.h>
#include <string.h> // for strcpy(), strlen()
#include <stdlib.h> // for malloc()
int main(void) {
char **sweet_names; // make a double pointer(or you might see that as array of pointers
char reader[300]; // this variable will help us read every name into the sweet_names
int sweet_number;
int i, j;
// Your code here to get the number of sweet_names
/*Prompts the user to enter the number of sweets and saves it to sweet_number*/
printf("Please enter the number of sweets:\n");
scanf("%d", &sweet_number);
// Now that you know the sweet_number, allocate as much memory as you need.
// And that can be more than 999 sweet names
sweet_names = (char **) malloc(sweet_number * sizeof(char *));
// i.e. make a character pointer to sweet_number character pointers.
// Again, some of your code here
for (i = 0; sweet_number > i; i++) {
printf("What is the name of the sweet?\n");
scanf("%s", reader); // read into the reader
sweet_names[i] = (char *) malloc(strlen(reader) + 1); // allocate as much memory as you need for the current string, the one just read into reader
strcpy(sweet_names[i], reader); // copy contents of reader to sweet_names[i]
}
// Again, your code to print the names
for (j = 0; sweet_number > j; j++){
printf("%s\n", sweet_names[j]);
free(sweet_names[j]); // free every string you allocated, it is good practice
}
// Finally, free the sweet_names pointers. Generally, when you allocate
// dynamically, which is what we do with malloc(), it is a good practice
// to free what you allocate becuase otherwise stays in memory and then
// memory leaks are created. There is a lot to say about C and memory
// but anyway, remember to free
free(sweet_names);
return 0;
}
Finally, now the program again has the limitation to read only names up to 300 characters because of reader, but this is something that you can also deal with, and this is to allocate a crazy amount of memory for reader, like 1000000
characters and then free it.

Resources