C - segmentation fault when comparing integers - c

here is a part of my code. When I run my code, it's requesting an input from user and then matching it with another integer which recorded in my structure. When user input is matching, it is working correct. But when user enters a wrong input, it gives a segmentation fault. In where, I should make changes on my code?
long int userInput,endCheck; // Input from user
int flag=0; // check for match
int status;
int c; // controlling ctrl+D
int position= 999; // position of where the user input and data matched
LABEL:
printf("\n\t---------------------------------------\n");
printf("\n\nPlease enter the student ID which you want to find(3-times CTRL+D for finish):\n");
scanf("%d",&userInput);
if( (c=getchar()) == EOF){
exit(0);
}
for(i=0;i<lines,flag==0;i++){
if(index[i].id == userInput){
position=i;
flag=1;
}else{
position=999;
}
}
if(flag==0){
printf("id not found");
}
studentInfo info; // for storing the information which we will take between determined offsets
if(position!= 999){
if ( (pos = lseek(mainFile,index[position].offset , SEEK_SET)) == -1)/*going to determined offset and setting it as starting offset*/
{ perror("classlist"); return 4; }
while ( (ret= read(mainFile,&info, sizeof(info))) > 0 ){
printf("\n\nStudent ID: %d, Student Name: %s\n\n",info.id,info.name);
break;// to not take another students' informations.
}
}
flag=0;
goto LABEL;
printf("Program is terminated");

The right way to do that loop with the unwanted comma is like this. When you find the right index[i].id you can exit the loop early by using break.
for(i=0;i<lines;i++){
if(index[i].id == userInput){
position=i;
flag=1;
break;
}
}
You don't need the else branch as position is set to 999 from the outset of the code. But really you shouldn't use position in this fashion. What if you have more than 999 records? You're already using flag to identify if you've set position to a valid value. You should replace any instance of if(position!= 999) with if(flag).
Or since position is a signed int, you could use a negative value and ditch the flag.

The reason can be the fact that you are reaching an index that doesn't exist in the end of cycle, in the moment of the "if" statement with iterator "i".
Or in the last if, where you access a "position" index of the array. Check those limits.
Also, try GDB, is useful for solving this kind of problems.

Related

Variable loses its value C

I'm working on this project where a user has to guess a word (wordToGuess) and he has a number of attempts.
The problem is that the variable "wordToGuess" loses its value when the code arrives in the point marked ("HERE LOSES ITS VALUE). I don't know how to solve this problem, I've tried in many ways. Thank u for your help!
(checkExistence is a function that checks if the word is present in the dictionary)
void newGame(node* head){
char wordToGuess[10];
char attempt[10];
int numberOfAttempts = 0;
if (scanf("%s" , wordToGuess) != 1){
printf("error1");
}
getchar();
if (scanf("%d", &numberOfAttempts) != 1){
printf("error2");
}
getchar();
while(numberOfAttempts > 0){
if (scanf("%s", attempt) != EOF){
if (attempt[0] != '+'){
if (checkExistence(head, attempt) == false){
printf("not_exists\n");
}else{
if (strcmp(wordToGuess, attempt) == 0){
printf("ok\n");
return;
}else{
//code
numberOfAttempts--;
}
}
}else{
if (attempt[0] == '+' && attempt[1] == 's'){
//HERE LOSES ITS VALUE
}else if (attempt[0] == '+' && attempt[1] == 'i'){
//other code
}
}
}else{
printf("ko");
return;
}
}
return;
}
Here a test case:
2rj9R (wordToGuess)
18 (numerAttemps)
DP3wc (attempt)
7PGPU (attempt)
2rz9R (attempt)
+print_list (from this point I lose the value of wordToGuess)
2rj9R (attempt)
As the others have point, you're probably causing a buffer overflow in your attempt buffer which overwrites your wordToGuess buffer since your attempt and wordToGuess buffer is stored like this in your memory:
<attempt buffer> | <word To Guess>
You have two possible fixes for this (as the comments have said...):
A little fix would be to set a limit of how many characters should be read from stdin to scanf like this:
scanf("%9s" , wordToGuess) // you need 9, because your buffer can store up to
// 10 bytes but don't forget that `scanf` is also
// addinng `\0` for you!
and don't forget to flush the rest of the user input if you want that the user should be only able to insert at most 9 characters!
Increase the buffer size of your attempt (and wordToGuess) buffer but also add those read-limits for scanf which is described in the first point.
At the indicated point of the code where wordToGuess appears to lose its value, it is a dead variable. If you're looking at optimized code in a debugger, you may find that the variable doesn't exist there any more.
At a given point in a program, a dead variable is one which is never used past that point. All control flows out of that point reach the termination of that code, without ever using the variable again. Simple example:
{
int x = 3;
// x is live here: there is a next reference
printf("%d\n", x);
// x is now dead: it is not referenced after the above use
printf("foo\n");
}
In the generated code, the compiler may arrange to re-use the resources tied to a dead variable as soon as it is dead: give its register and memory location to something else.
In the debugger, if we put a breakpoint on the printf("foo\n") and try to examine x, we might get a strange result.
To have the best chance of seeing the expected result (that x still exists, and is retaining its most recent value), we have to compile with optimizations disabled.

Nested if statement in C - why doesn't it evaluate the last else if?

The following code does not execute the last else if statement when you assign to choice value 3.
#include<stdio.h>
#include<stdlib.h>
int main() {
puts("Specify with a number what is that you want to do.");
puts("1. Restore wallet from seed.");
puts("2. Generate a view only wallet.");
puts("3. Get guidance on the usage from within monero-wallet-cli.");
unsigned char choice;
choice = getchar();
if ( choice == '1' ) {
system("nice -19 ~/monero-x86_64-linux-gnu-v0.17.2.0/monero-wallet-cli --testnet --restore-deterministic-wallet");
exit(0);
}
else if ( choice == '2' ) {
system("nice -19 ~/monero-x86_64-linux-gnu-v0.17.2.0/monero-wallet-cli --testnet --generate-from-view-key wallet-view-only");
exit(0);
}
else if ( choice == '3' ) {
puts("Specify with a number what is that you want to do.");
puts("1. Get guidance in my addresses and UTXOs");
puts("2. Pay");
puts("3. Get guidance on mining.");
unsigned char choicetwo = getchar();
if ( choicetwo == '1' ) {
printf("Use \033address all\033 to get all your addresses that have any balance, or that you have generated at this session.");
printf("Use \033balance\033 to get your balance");
printf("Use \033show_transfers\033 to get ");
printf("Use \033show_transfers\033 out to get ");
printf("Use \033show_transfers in\033 to get your balance");
}
}
return 0;
}
I get the following output When I enter 3:
Specify with a number what is that you want to do.
1. Restore wallet from seed.
2. Generate a view only wallet.
3. Get guidance on the usage from within monero-wallet-cli.
3
Specify with a number what is that you want to do.
1. Get guidance in my addresses and UTXOs
2. Pay
3. Get guidance on mining.
I'm really blocked, something is missing and I have no clue why it does not proceed to take the input from the user for the second time.
When you enter "3" for the first input, you're actually inputting two characters: the character '3' and a newline. The first getchar function reads "3" from the input stream, and the second one reads the newline.
After accepting the first input, you'll want to call getchar in a loop until you read a newline to clear the input buffer.
choice = getchar();
while (getchar() != '\n');

Nested While Loops in C

I am having issues making this nested while loop to work in this terminal application.I am trying to build a system with Clients and an Admin with certain
capabilities for each.
scanf("%s",sign_in_choice);
int admin_result, client_result, number_of_clients, x, c;
admin_result = strcmp(sign_in_choice,"Admin");
client_result = strcmp(sign_in_choice,"Client");
char client_choice[10];
int client_username;
int client_password;
int client_choice_log_in, client_choice_register;
while(x == 0)
{
if(admin_result == 0 )
{
printf("Welcome to Admin Page\n");
}
else if(client_result == 0)
{
printf("Testing");
while(c == 0)
{
//START OF CLIENT PAGE
printf("Welcome to Client Page\n");
printf("Register or Log in?\n");
scanf("%s",client_choice);
client_choice_log_in = strcmp(client_choice,"Login");
client_choice_register = strcmp(client_choice,"Register");
if(client_choice_register == 0)
{
// REGISTER
reg(client_number);
// END OF REGISTER
}
else if(client_choice_log_in == 0)
{
//LOG IN
printf("Please enter your credentials\n");
printf("Enter your afm:\n");
scanf("%d", &client_username);
printf("Enter your year of birth:\n");
scanf("%d", &client_password);
login(client_username, client_password, client_number, client_verify);
//END OF LOG IN
// PERSONAL CLIENT PAGE
i = client_number;
printf("Welcome to your Personal Client Page: %s \n", client_array[i].client_name);
printf("Verify : %d\n",client_verify);
// END OF PERSONAL CLIENT PAGE
}
else
{
printf("Invalid input.Please try again.\n");
scanf("%s",client_choice);
client_choice_log_in = strcmp(sign_in_choice,"Login");
client_choice_register = strcmp(sign_in_choice,"Register");
}
// END OF CLIENT PAGE
}
}
else
{
printf("Invalid input.Please try again.\n");
scanf("%s",sign_in_choice);
admin_result = strcmp(sign_in_choice,"Admin");
client_result = strcmp(sign_in_choice,"Client");
}
}
If I remove the while( c == 0) loop the code works.It allows me to select either Login or Register and continue.If I leave the loop as is when I input 'Client' the program goes into an infinite loop printing 'testing'.In addition if I enter 'Admin' the program again goes into infinite loop printing 'welcome to admin page' although the while loop appears later in the program.At least in my understanding the while(c == 0) loop should only affect what is contained within it not outside it,at least in this particular case.I am using Devc 5.11.Also I tried compiling and running through vs code and codeblocks and in those cases the program doesn't even go beyond the 'Admin Client' choice in the beginning.As you can see I have some functions and and structs not shown here but they should not affect my problem since everything works fine until I try to make this nested while loop work.
c is uninitialized, so it has an undefined behavior, which depends on your compiler. You will need to initialize your variables. And to make sure you do not have infinite loops, you must handle the case when you have a client and c is not 0. You can set it to 0, or something, just don't leave there an else which will always be entered, will not change c and will have a loop inside it, which depends on the value of c.
Maybe I missed it, but I do not see how you set the value of c inside the while (c == 0) loop, so if c happens to be 0, that inner loop seems to be infinite as well.

Why my c program only produce zero answer while using for loop?

I tried to use for loop calculate the number of books keyed in and sum up their total price, but at the end i only get zero price in C program. What is my problem ? How to solve it?
#include<stdio.h>
int main(void)
{
int booknum;
float bookfee,bookgst,nogst,totfee,newfee,newfee_nogst;
bookgst=0.0;
nogst=0.0;
int cnt;
char code;
printf("Key in total books purchased >> ");
scanf("%d",&booknum);
for(cnt=1;cnt<=booknum;cnt++)
{
printf("\n\n");
printf("Key in price of the book >> ");
scanf("%f",&bookfee);
printf("Key in type( S=standard gst,Z=zero gst) \n>> ");
scanf("%c",&code);
getchar();
if(code=='S')
{
newfee=bookfee+0.6;
}
else if(code=='Z')
{
newfee_nogst=bookfee;
}
bookgst=bookgst+newfee;
nogst=nogst+newfee_nogst;
printf("\n");
}
totfee=bookgst+nogst;
printf("Book purchased with GST : RM %.2f\n",bookgst);
printf("Book purchased without GST : RM %.2f\n",nogst);
printf("Total payment : RM %.2f\n",totfee);
return 0;
}
There are a few problems with this code, but you're almost there!
First code reading needs to eat the previous \n (see this), otherwise the code is neither Z not S (it's a newline), and that's why the fees are never added.
(Search also for "fgets vs scanf" to see how to use the safer fgets).
scanf(" %c",&code);
then these lines
bookgst=bookgst+newfee;
nogst=nogst+newfee_nogst;
add the newfee / newfee_nogst ; these variables are set to 0 before the loop, but at the next occurence, they're still set to the value of the previous occurrence, thus either set them to 0 at the beginning of the loop, or, add the value directly in the if (see below). And since we're here, print an error if the code is wrong (and maybe subtract one to cnt to do one more loop with a correct code, in this case).
Also, the GST calculation is probably wrong, 6% of x is 0.06 * x, and if you want GST added to the value that's x * 1.06
if(code=='S')
{
bookgst = bookgst + bookfee*1.06; // or bookgst += bookfee*1.06
}
else if(code=='Z')
{
nogst = nogst + bookfee; // or nogst += bookfee
}
else {
printf("Code not understood\n");
}

Unable to stop the function when the condition its true

I'm doing a program where you can add items for a shop. Before the user can be allowed to do that, theres a subfunction which will ask for a user and password; if they are correct then allows the user to add any item as far he wants, also there's a variable called count if this variable goes to "0" should print and error and several noises and after that bring back the user to the main function and close the program.
The problem is after the condition is 0 the noises and error shows correctly but the program backs to ask for user and password and the count variable starts at 0 and every try rest the int...-1 -2 -3.
So I try this, even its working I think it's a pretty bad way:
The call
while(credencial !=1)
{
credencial=checkout(&counter);
if(counter==88)
{
goto error;
}
}
Function
int checkout(int *counter){
char login[10], password[10];
int c = 0;
printf("\nNumero de intentos restantes: %d\n", *counter);
puts("\nIntroduce un usuario con credenciales: \n");
scanf("%10s", login);
puts("\nIntroduce la contraseƱa: \n");
scanf("%10s", password);
(*counter)--;
if (*counter == 0)
{
system("cls");
for (c = 0 ;c < 3 ;c++)
{
puts("\n\aACCESSO DENEGADO\n");
}
*counter=88;
}
if (strcmp(strlwr(login), "admin") ==0 && strcmp(strlwr(password),"admin")==0)
{
return 1;
}
}
You can either use break; to leave the while loop (then you need to have a way to decide after the loop if it is a normal or error exit, for example by checking credential value) or add an additional condition to the while, like
while(credentiel != -1 && !abort) {
....
if (*counter == 88)
abort = true;
Or cou can use the goto, it is not that bad. Especially if the error label is used by other places as well.
BTW: I don't know why you mix out variables with return types and why you use 88 as a special number. Thats all quite untypical. You can keep the counter in the outer loop and make the crendtial check stateless, let it return pass/fail only. It is more common to use negative values (-1) for special "signals". In all cases make sure nobody can force the special value with other tricks.

Resources