C sscanf change other value [duplicate] - c

This question already has answers here:
Input too big for array
(4 answers)
Closed 2 years ago.
When I use sscanf, I found some other variable is changed as well but I don't know why.
My code is:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int add(int a, int b) {
return a + b;
}
int sub(int a, int b) {
return a - b;
}
int mul(int a, int b) {
return a * b;
}
int d(int a, int b) {
return a / b;
}
void manipulate(int* result, int x, int y, int op(int, int)) {
printf("%p\n", result);
*result = op(x, y);
}
int main() {
char line[20];
FILE* f = fopen("sample.txt", "r");
int result = 0;
while (fgets(line, 15, f) != NULL) {
char oper[3];
char valA[3];
char valB[3];
sscanf(&line[0], "%s %s %s", oper, valA, valB);
int x;
int y;
printf("%d\n", result);
if (valA[0] == '%') {
x = result;
y = atoi(valB);
} else if (valB[0] == '%') {
x = atoi(valA);
y = result;
} else {
x = atoi(valA);
y = atoi(valB);
}
printf("%d %d\n", x, y);
if (strcmp(oper, "ADD") == 0) {
manipulate(&result, x, y, &add);
} else if (strcmp(oper, "SUB") == 0) {
manipulate(&result, x, y, &sub);
} else if (strcmp(oper, "MUL") == 0) {
manipulate(&result, x, y, &mul);
} else if (strcmp(oper, "DIV") == 0) {
manipulate(&result, x, y, &d);
}
}
}
I used the debugger to track the value of the variable named result. In the first loop, the result becomes the value I want, but when it entre the second loop and finish the line sscanf, the result becomes 0 again. Could anyone tell me why? Thank you so much :)

Your char arrays are too small, because you didn't account for null terminators. The string ADD requires 4 characters ('A', 'D', 'D', and '\0'), but you're storing it in char oper[3], and writing past the end is Undefined Behavior. In this case, that happens to mean that the '\0' gets stored on top of result, setting it to 0.

Related

Void Factorial Using Pointers in C

I want to do a void factorial function in C that uses pointers. This is my code but it won't run.
#include <stdio.h>
void factorial(int, int*);
int main()
{
int n;
int r = 0;
printf("Enter n : ");
scanf("%d", &n);
if (n < 0)
{
printf("No factorial for negative");
}
else
{
factorial(n , &r);
printf("factorial of %d is %d", n, r);
}
}
void factorial(int n , int *r)
{
if (n == 0 || n == 1)
{
*r= 1;
}
else
{
*r= n* factorial((n-1), r);
}
}
The error I get is in the last line of the code saying : invalid operands of type "int" and "void" to binary operator * , what does that mean and how to fix it?
Well, if factorial() returns void (which is basically , returning nothing) , this line does not make any sense
*result = num * factorial ((num-1), result);
It's because factorial() returns void.
Try:
factorial((num-1), result);
*result= num *(*result);
Instead of that line.
You cannot use return value of a function if it is declared to return void.
If you want to declare function this way then your factorial function can be:
void factorial(int num , int *result)
{
if (num == 0 || num == 1)
{
//*result = 1;
return;
}
else
{
*result *= num;
factorial ((num-1), result);
}
But also in main function you should change int res = 0 into int res = 1.
void Factorial(int *a,int *result){
if (*a == 0 || *a == 1){
return;
}
else{
*result *= *a;
*a -= 1;
Factorial(a,result);
}}

Use of just while(x)

#include<stdio.h>
#include<conio.h>
/* Function Declaration
int pal(int x); */
/*Declaring Second Function*/
int rev(int x);
int main()
{
int a, b, c;
clrscr();
printf("Enter The Number Which You Want To Check Is Palindrome Or Not\n");
scanf("%d", &a);
b = rev(a);
printf("%d", b);
if(b == a) {
printf("%d Is A Palindrome Number", a);
} else {
printf("%d Isn't A Plaindrome Number", a);
}
getch();
return(0);
}
int rev(int x)
{
int d = 0;
while(x) {
d = d * 10 + x % 10;
x = x / 10;
}
return(d);
}
I didn't get the use of while(x) statement. I mean, we attach some condition with while loop i.e. while(x!=0), so what does standalone while(x) means.
while (x) is the same as while (x != 0)
For an integral data type, 0 is false & everything else is true. So while (x) would evaluate to while(true) for all x != 0.
Similarly, you will also come across expressions like while(!x) or if(!x)
If x has value a non zero value, then x is true & !x is false.
If x has value 0, then x is false & !x is true.
So writing (!x) is the same as writing (x == 0)
You will also see similar usage with pointers. For a pointer p, (p) is the same as (p != NULL) and (!p) is the same as (p == NULL).

Pointer Division possible? [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 8 years ago.
Improve this question
How can i divide and multiplicate 2 variables in C with Pointers?
I tried this:
int multiplicate(int *x,int *y)
{
*x**y;
}
int divide(int *x,int *y)
{
*x/*y;
}
You are missing the return statement:
int multiplicate(int* x, int* y)
{
return (*x) * (*y);
}
int divide(int *x,int *y)
{
return (*x) / (*y);
}
Use *x/(*y) instead. Else it's interpreted as a multiline comment. And you forgot return
Since the indirection operator has higher precedence that multiplication operator, parenthesis are not needed.
Simply adding some whitespace will do:
int multiplicate(int *x,int *y)
{
return *x * *y;
}
int divide(int *x,int *y)
{
return *x / *y;
}
Pointer Division possible?
You do not try to devide pointers here, but as using the dereferencing *-operator, the values the pointers are pointing to are use.
However, as all examples given so far fully miss essential error checking, I propose the following approaches:
int multiply(int * pr, int * px, int * py)
{
int result = 0; /* Be optimistic. */
if (NULL == pr || NULL == px || NULL == py)
{
errno = EINVAL;
result = -1;
}
else
{
*pr = *px * *py;
}
return result;
}
int devide(int * pr, int * px, int * py)
{
int result = 0; /* Be optimistic. */
if (NULL == pr || NULL == px || NULL == py)
{
errno = EINVAL;
result = -1;
}
elseif (0 = *py) /* Division by zero is not defined. */
{
errno = EDOM;
result = -1;
}
else
{
*pr = *px / *py;
}
return result;
}
Call those functions like this:
#include <stdio.h>
#include <errno.h>
/* The two functions above go here. */
int main(int argc, char ** argv)
{
int result = EXIT_SUCCESS;
if (2 > argc)
{
fprintf("Missing or invalid arguments.\n");
printf("Usage: %s x y\n", argv[0]);
result = EXIT_FAILURE;
}
if (EXIT_SUCCESS == result)
{
int x = atoi(argv[1]); /* Better use strtol here. */
int y = atoi(argv[2]); /* Better use strtol here. */
printf("Got x = %d and y = %d.\n", x, y);
{
int r;
if (-1 == multiply(&r, &x, &y)
{
perror("multiply() failed");
}
else
{
printf("%d * %d = %d\n", x, y, r);
}
}
{
int r;
if (-1 == multiply(&r, &x, &y)
{
perror("devide() failed");
}
else
{
printf("%d / %d = %d\n", x, y, r);
}
}
}
return result;
}
Finally a more sane approach would be to use pointers only where needed.
A possible approch modifying the above examples would look like this:
int multiply(int * pr, int x, int y)
{
int result = 0; /* Be optimistic. */
if (NULL == pr)
{
errno = EINVAL;
result = -1;
}
else
{
*pr = x * y;
}
return result;
}
int devide(int * pr, int x, int y)
{
int result = 0; /* Be optimistic. */
if (NULL == pr)
{
errno = EINVAL;
result = -1;
}
elseif (0 = y) /* Division by zero is not defined. */
{
errno = EDOM;
result = -1;
}
else
{
*pr = x / y;
}
return result;
}
Call those functions like this:
#include <stdio.h>
#include <errno.h>
/* The two functions above go here. */
int main(int argc, char ** argv)
{
int result = EXIT_SUCCESS;
if (2 > argc)
{
fprintf("Missing or invalid arguments.\n");
printf("Usage: %s x y\n", argv[0]);
result = EXIT_FAILURE;
}
if (EXIT_SUCCESS == result)
{
int x = atoi(argv[1]); /* Better use strtol here. */
int y = atoi(argv[2]); /* Better use strtol here. */
printf("Got x = %d and y = %d.\n", x, y);
{
int r;
if (-1 == multiply(&r, x, y)
{
perror("multiply() failed");
}
else
{
printf("%d * %d = %d\n", x, y, r);
}
}
{
int r;
if (-1 == multiply(&r, x, y)
{
perror("devide() failed");
}
else
{
printf("%d / %d = %d\n", x, y, r);
}
}
}
return result;
}

Assigning value to struct variable

I am constructing a adjacency list that I am using to make a directed graph. I read two characters and then make a vertex out of each of them unless a vertex with that char has already been made. I am unfamiliar with structures so this is tripping me up. The values aren't being assigned and I am ending up with an empty list. I am assuming that it is something that has to do with pointers that I am overlooking but I can't seem to find the problem. I hope that someone can help. I will include my code and a sample output.
my.h
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
/* Forward declaration */
struct EDGETAG;
typedef struct
{
char c;
bool isVisited;
struct EDGETAG* p;
} VERTEX;
typedef struct EDGETAG
{
VERTEX* v;
struct EDGETAG* q;
} EDGE;
int main (int argc, char* argv[]);
int adjListSearch (char a, int size, VERTEX* adjList);
adjListSearch.c
#include "my.h"
int adjListSearch (char a, int size, VERTEX* adjList)
{
int i;
if(size == 0)
{
printf("empty\n");
return 1;
}
for(i = 0; i<size; i++)
{
if( adjList[i].c = a)
{
return 0;
printf("found\n");
}
}
printf("notfound\n");
return 1;
}
main.c
#include "my.h"
int main (int argc, char* argv[])
{
int y = 0;
int x = 0;
VERTEX *adjList;
adjList = (VERTEX*)calloc(26, sizeof(VERTEX));
//adjList = malloc(sizeof(VERTEX)*26);
FILE* p;
char *fp;
char a;
char b;
int check1 = 0;
int check2 = 0;
int size = 0;
int searchsuccess = 0;
int i;
//Statements
p = fopen( argv[1], "r");
while(fscanf(p," %c %c", &a, &b)!= EOF)
{
printf("a: %c b: %c\n",a,b);
check1 = adjListSearch(a,size,adjList);
if(check1==1)
{
adjList[size].c = a;
size = size +1;
}
//printf("%c\n", adjList[size].c);
check2 = adjListSearch(b,size,adjList);
if(check2==1)
{
adjList[size].c = b;
size = size +1;
}
}
//End While
printf("Size: %d", size);
for(i=0;i<size;i++)
{
printf("%c\n", adjList[size].c);
}
free(p);
return 0;
}
//End main
Sample Output
a: A b: B
a: B b: C
a: E b: X
a: C b: D
Size: 1
As you can see none of the characters are printed as being inside a structure.
EDIT 1:
I would want the expected output to look like
a: A b: B
a: B b: C
a: E b: X
a: C b: D
Size: 6
A
B
C
E
X
D
Edit 2
Still lost on this if anyone can help.
There were a variety of problems.
You should use fclose(p); and not free(p);.
You should print printf("%c\n", adjList[i].c); instead of printf("%c\n", adjList[size].c);.
As brokenfoot pointed out in his answer, you need to compare a instead of assign it in adjListSearch().
There were multiple unused variables (the compilation options I use complain about them).
There is no need to declare main() (though it doesn't do any harm to the program).
You don't check that there is an argv[1] to use.
You don't check that you opened the file.
You should really use while (fscanf(p, " %c %c", &a, &b) == 2), though it would only matter in this program if there were an odd number of characters to process. At least you were testing fscanf() which is more than many questions we see do.
In the code below, I printed more informative status messages.
main.c
#include "my.h"
int main(int argc, char *argv[])
{
VERTEX *adjList;
adjList = (VERTEX *)calloc(26, sizeof(VERTEX));
FILE *p;
char a;
char b;
int check1 = 0;
int check2 = 0;
int size = 0;
int i;
if (argc != 2)
{
fprintf(stderr, "Usage: %s file\n", argv[0]);
return 1;
}
if ((p = fopen(argv[1], "r")) == 0)
{
fprintf(stderr, "Failed to open file %s for reading\n", argv[1]);
return 1;
}
while (fscanf(p, " %c %c", &a, &b) == 2)
{
printf("a: %c b: %c\n", a, b);
check1 = adjListSearch(a, size, adjList);
if (check1 == 1)
{
printf("Adding a = %c\n", a);
adjList[size++].c = a;
}
check2 = adjListSearch(b, size, adjList);
if (check2 == 1)
{
printf("Adding b = %c\n", b);
adjList[size++].c = b;
}
}
printf("Size: %d\n", size);
for (i = 0; i < size; i++)
{
printf("%c\n", adjList[i].c);
}
fclose(p);
return 0;
}
adjListSearch.c
#include "my.h"
int adjListSearch(char a, int size, VERTEX *adjList)
{
int i;
if (size == 0)
{
printf("empty\n");
return 1;
}
for (i = 0; i < size; i++)
{
if (adjList[i].c == a)
{
printf("found %c\n", a);
return 0;
}
}
printf("not found %c\n", a);
return 1;
}
Data
A B
B C
E X
C D
Sample output
a: A b: B
empty
Adding a = A
not found B
Adding b = B
a: B b: C
found B
not found C
Adding b = C
a: E b: X
not found E
Adding a = E
not found X
Adding b = X
a: C b: D
found C
not found D
Adding b = D
Size: 6
A
B
C
E
X
D
In adjListSearch(), change
if( adjList[i].c = a)
to
if( adjList[i].c == a)

function and pointers

I'm trying to write a program that would convert celcius to fahrenheit and visa-versa. My program is compiling, but it gives me wrong results. I'm been trying to change it by changing pointers, but it wouldnt work. Can anyone please point out to me what is my problem? It seems to me it's in declarations and pointers, but i'm not sure.Thanks!
#include<stdio.h>
float f2c(float f);
float c2f(float c);
int main(void)
{
float cel;
float celcius;
float fahren;
float fah;
char ch;
float number;
scanf("%c %f", &ch, &number);
if(&ch == "-f"){
f2c(number);
celcius=f2c(number);
printf("%f", celcius);
}
else{
c2f(number);
fahren = c2f(number);
printf("%f", fahren);
}
return 0;
}
float f2c(float f)
{
float cel = (f - 32) * 5/9;
return cel;
}
float c2f(float c)
{
float fah = (9 * c/5 + 32);
return fah;
}
if(&ch == "-f") this is the problem.
It should be :
if(ch == 'f')
In addition to the other answers:
You are doing needless calls to the conversion functions and throwing away the results, just before doing the same calls again but with proper handling of the return value:
if(&ch == "-f"){
f2c(number); /* This line does absolutely nothing! */
celcius=f2c(number);
printf("%f", celcius);
}
You are comparing char with a C-string "-f". Use strcmp to compare C-strings.
You may also have declare ch as char array to more than one character which you need here. Because, you can't store "-f" in a single char as you do now.
With the changes:
#include<stdio.h>
float f2c(float f);
float c2f(float c);
int main(void)
{
float cel;
float celcius;
float fahren;
float fah;
char ch[25];
float number;
scanf("%s %f", ch, &number);
if(strcmp(ch,"-f")==0){
f2c(number);
celcius=f2c(number);
printf("%f", celcius);
}
else{
c2f(number);
fahren = c2f(number);
printf("%f", fahren);
}
return 0;
}
float f2c(float f)
{
float cel = (f - 32) * 5/9.0;
return cel;
}
float c2f(float c)
{
float fah = (9 * c/5.0 + 32);
return fah;
}
This is essentially your code, but modified it to read the input as C-string.
Use floating-point arithmetic, not integer arithmetic, because in integer arithmetic, 5/9 is 0. So you could make this change to your code (though float parameters are unusual):
float f2c(float f)
{
return (f - 32.0) * 5.0/9.0;
}
float c2f(float c)
{
return 9.0 * c/5.0 + 32.0;
}
Also as one of the other answers states, the condition (&ch == "-f") is never true.
Here is a complete working example, with error checking.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <errno.h>
#include <assert.h>
static double f2c(double f)
{
return (f - 32.0) * 5.0/9.0;
}
static double c2f(double c)
{
return 9.0 * c/5.0 + 32.0;
}
int main (int argc, char *argv[])
{
int i;
const char *label_f = "Fahrenheit";
const char *label_c = "Celcius";
const char *from, *to;
double (*conversion)(double);
from = label_c;
to = label_f;
conversion = c2f;
for (i=1; i<argc; ++i)
{
if (0 == strcmp(argv[i], "-f"))
{
from = label_f;
to = label_c;
conversion = f2c;
}
else if (0 == strcmp(argv[i], "-c"))
{
from = label_c;
to = label_f;
conversion = c2f;
}
else
{
char *suffix = NULL;
double temp_in;
errno = 0;
temp_in = strtod(argv[i], &suffix);
if (ERANGE == errno)
{
if (HUGE_VAL == temp_in)
{
fprintf(stderr, "%s is too big", argv[i]);
return 1;
}
else
{
assert(-HUGE_VAL == temp_in);
fprintf(stderr, "%s is too small", argv[i]);
return 1;
}
}
else if (errno != 0 && (suffix == argv[i]))
{
/* no conversion was performed. */
fprintf(stderr, "%s is not a number", argv[i]);
return 1;
}
else if (*suffix)
{
fprintf(stderr, "Expected a number but saw '%s'\n", argv[i]);
return 1;
}
else
{
const double temp_out = (*conversion)(temp_in);
printf("%f %s is %f %s.\n", temp_in, from, temp_out, to);
}
}
}
return 0;
}

Resources