I am playing around with this code from one of my lecture slides and one of my questions is when printing out the array why can't we use the pointer instead of just printing "a", In the last line of the print statement
printf("\n message after decryption: %s\n", a);
I don't see why we cant use a pointer to print out the array. Can someone explainto me why this can't be done?
printf("\n message after decryption: %s\n", *q);
#include <stdio.h>
#define NUM 78
int main()
{
int i = 0;
char a[] = "Hello CSE 240";
printf("\n message: %s\n ", a);
while(a[i] != '\0'){a[i] = *(a+i)+1;i++;}
printf("\n message after encryption: %s\n ", a);
char *q = a;
while(*q != '\0'){*q = *q-1;q++;}
printf("\n message after decryption: %s\n", a);
}
You want to print out the content of the array after the q modification loop but it after all the increment it points to the null termination character i.e. '\0' - hence using q in printf will print this only - message after decryption: - modified array/string will not be printed.
To do it with q you need to reassign q to the first element of the array: q=a after the while loop ends.
and then this statement will work as you wish:
printf("\n message after decryption: %s\n", q);
It is good that you have changed the print statement with the suitable format specifier.
#include <stdio.h>
#define NUM 78
int main()
{
int i = 0;
char a[] = "Hello CSE 240";
printf("\n message: %s\n ", a);
while(a[i] != '\0'){a[i] = *(a+i)+1;i++;}
printf("\n message after encryption: %s\n ", a);
char *q = a;
while(*q != '\0'){*q = *q-1;q++;
//decrypting the value of a
}//end of this is pointing to null
q=a;//repointing to point a
printf("\n message after decryption: %c\n", *q);//H is printed
printf("\n message after decryption: %s\n", q);//Hello CSE 240 is printed
}
Related
I am programming a registration system using array strings for postal code and home address. I use a constant to determine the postal code limit of just 8 characters.
When the program start the register function, it makes the address and postal code inputs correct, but when I list it, the address appears normal and the postal code of position 1 together with the others below. Why is this happening? I put 8 character positions for the postal code and it increases by placing the second one as well.
My program:
#include <stdio.h>
#define LIMIT_POSTAL 8
#define LIMIT_REGISTER 5
#define LIMIT_ADDRESS 20
char postal_c[LIMIT_REGISTER][LIMIT_POSTAL], address[LIMIT_REGISTER][LIMIT_ADDRESS];
int line;
void reg()
{
int op;
do
{
printf("Address: ");
scanf("%s", &address[line]);
printf("Postal code: ");
scanf("%s", &postal_c[line]);
op = -1;
printf("1 - Continue\nAny number - Exit\n");
scanf("%d", &op);
line++;
} while(op == 1);
}
int main()
{
int i;
reg();
for(i = 0; i < line; i++)
{
printf("Address: %s\n", address[i]);
printf("Postal: %s\n", postal_c[i]);
}
return 0;
}
Output:
Address: foo
Postal code: 11111111
1 - Continue
Any number - Exit
1
Address: foo2
Postal code: 22222222
1 - Continue
Any number - Exit
0
Address: foo
Postal: 1111111122222222
Address: foo2
Postal: 22222222
In your code probably:
#include <stdio.h>
#define LIMIT_POSTAL 8
#define LIMIT_REGISTER 5
#define LIMIT_ADDRESS 20
char postal_c[LIMIT_REGISTER][LIMIT_POSTAL], address[LIMIT_REGISTER][LIMIT_ADDRESS];
int line;
void reg()
{
int op;
do
{
printf("Address: ");
scanf("%s", &address[line]);
printf("Postal code: ");
scanf("%s", &postal_c[line]);
op = -1;
printf("1 - Continue\nAny number - Exit\n");
scanf("%d", &op);
line++;
} while(op == 1);
}
int main()
{
int i;
reg();
for(i = 0; i < line; i++)
{
printf("Address: %s\n", address[i]);
printf("Postal: %s\n", postal_c[i]);
}
return 0;
}
I can't see you had initialized line variable in you program and you are using it directly to pointing the index, hence you didn't assigned any value so probably it contains garbage value and pointing invalid memory address in your program.
I am assuming your rest code is correct.
try doing...
int line =0;
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int n, k;
scanf("%d %d", &n, &k);
printf("%d %d\n", n, k);
return 0;
}
In the above sample code passing to the input
1 2
Would produce an expected output of
1 2
However passing any char in-between these two digits such as
1. 2 or 1 d 3
Will result in a strange output of the following
1 32766
I would like to know why this occurs, as it was to my belief that scanf would skip over any non-digit input.
You should check the return value of scanf, which tells you the number of data that are read into the passed arguments, here it is k.
In your case, the return value will be zero as %d cannot be used to read in a char in C. If the first input is a char it will be 0, 1 if the first value is int and the second value is a char, 2 if both of the values are int.
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int n, k, rc;
rc = scanf("%d %d", &n, &k);
if (rc != 2)
{
printf("scanf failed to set the values for n and k\n");
}
else
{
printf("valid input for n and k\n");
}
printf("%d %d\n", n, k);
return 0;
}
So the int k is uninitialized and thus it will store some random value as scanf failed to set the value for this variable.
(Too long for a comment.) The following answers OP's followup question from a comment.
is there anyway to pass over the character that stops the input stream?
scanf may not be the best or easiest way to do that, but it's still possible to do it using the %n format specifier which returns the offset into the original string during parsing. Following is an example, which uses sscanf but can be easily adapted to scanf.
#include <stdio.h>
void read_three_ints(const char *str) {
int a, n1, b, n2, c;
int ret = sscanf(str, "%d %n%d %n%d", &a, &n1, &b, &n2, &c);
switch(ret)
{
case 3:
printf("'%s': a = %d, b = %d, c = %d\n", str, a, b, c);
break;
case 2:
printf("'%s': a = %d, b = %d, error parsing c = `%s`\n", str, a, b, str + n2);
break;
case 1:
printf("'%s': a = %d, error parsing b = `%s`\n", str, a, str + n1);
break;
case 0:
printf("'%s': error parsing a\n", str);
break;
default:
printf("'%s': scanf error %d\n", str, ret);
break;
}
}
int main()
{
read_three_ints("1 2 3");
read_three_ints("1 2 x");
read_three_ints("1, 2 ");
read_three_ints(";1 ");
read_three_ints("");
return 0;
}
Output:
'1 2 3': a = 1, b = 2, c = 3
'1 2 x': a = 1, b = 2, error parsing c = `x`
'1, 2 ': a = 1, error parsing b = `, 2 `
';1 ': error parsing a
'': scanf error -1
Here is some simple code that prints struct values
in_hotel_info function is used to get struct inputs.(And yes, I use 'gets' because my professor forced me to use it sadly). And also When I put "0" as an input, it ends and returns its input numbers.
And I used sscanf to scan strings and numbers.
#include <stdio.h>
typedef struct hotel_info hotel;
struct hotel_info
{
char name[30];
int rank;
double popular;
double far;
char breakfast;
};
int in_hotel_info(struct hotel_info *p);
void out_hotel_info(struct hotel_info *p, int N, int G, double D);
int main(void)
{
hotel hotels[100];
hotel *p;
int number = 0, ranks, fars, i;
number = in_hotel_info(hotels);
p = hotels;
printf("%d\n", number);
getchar();
for (; p < p+number; p++)
{
printf("%s %d %lf %lf %c\n", p->name, p->rank, p->popular, p->far, p->breakfast);
}
}
int in_hotel_info(struct hotel_info infos[])
{
char inputs[100];
hotel* p;
p = infos;
int cnt = 0;
while (1)
{
gets(inputs);
if (strcmp(inputs, "0") == 0)
{
break;
}
else
{
sscanf(inputs, "%s %d %lf %lf %c", p->name, &p->rank, &p->popular, &p->far, &p->breakfast);
}
p++;
cnt++;
}
return cnt;
}
The problem is, when I tried to print
for (; p < p+number; p++)
{
printf("%s %d %lf %lf %c\n", p->name, p->rank, p->popular, p->far, p->breakfast);
}
what I expected is
mike 2 3.5 4.24 Y
but I constantly got a segmentation error.
The problem is, when I tried to print
for (; p < p+number; p++)
{
printf("%s %d %lf %lf %c\n", p->name, p->rank, p->popular, p->far, p->breakfast);
}
the problem is p < p+number is always true when number is strictly positive, so the for never ends and you access out of the array with an undefined behavior (your segmentation fault).
you have additional problems
gets is very dangerous to use because it can write out of the array, use fgets or scanf (secifying max length to read), in the considered case you can read a number then check if it is 0 or not
in in_hotel_info in case the user enter more than than entrie you write out of the array, you need to get the max number of element to read in argument
when you read p->name in case the enter name longer than 29 you write out of the array, limit the size using %29s rather than %s. ALso to bypass spaces at the beginning of the name use %29s (with a space before)
you do not check scanf returns 5, so you do not detect invalid inputs
The getchar(); in main is strange
I'm studying buffer overflow, and I'm trying to jump to the function 'confused' and then print out "done" at the end of main by performing buffer overflow.
#include<stdio.h>
#include<stdlib.h>
int i, n;
void confused(int i) {
printf("**Who called me? Why am I here?? *** %x\n ", i);
;
}
void shell_call(char *c) {
printf(" ***Now calling \"%s\" shell command *** \n", c);
system(c);
}
void victim_func(){
int a[4];
printf("\nEnter n: "); scanf("%d",&n);
printf("~~~~~~~~~~~~~ values and address of n locations ~~~~~~~~~~");
for (i = 0;i <n ;i++)
printf ("\n a[%d] = %x, address = %x", i, a[i], &a[i]);
printf("\nEnter %d HEX Values \n", n);
// Buffer Overflow vulnerability HERE!
for (i=0;i<n;i++) scanf("%x",&a[i]);
printf("Done reading junk numbers\n")
}
int main() {
printf("\n ~~~~~~~~~~~~~~~~~ Info Menu ~~~~~~~~~~~~");
printf("\n addrss of main %x", main);
printf("\n addrss of shell_cal %x", shell_call);
printf("\n addrss of confused %x", confused);
victim_func();
printf("\n done");
return 0;
}
What I did is I put 7 for n, and for 6th hex value I inserted the address of confused and for 7th the address of printf in main. It successfully prints out "done" after the confused function, but the program goes back to the start of main. I thought the program would terminate after printing out "done".
I just wonder if I did something wrong, or it is the way it should do.
You can always call exit() in your shell code to terminate the program. However, you can't do it using system(), because system() will create a child process which always ultimately return to it parent. You need to directly call exit() using assembly.
I've done this code so far but I don't get a final output (blank).
Output that I expected is when I put a string Hello World and replace o with i the string will be Helli Wirld. But I got nothing in the final output.
char * substitute(char *, char, char);
int main(void){
char arr[255];
char i,j;
printf("Enter a string: ");
gets(arr);
printf("Find a char: ");
scanf(" %c", &i);
printf("Replace with: ");
scanf(" %c", &j);
printf("Final output: ");
printf("%s", substitute(arr, i, j));
return 0;
}
char * substitute(char *data, char find, char replace){
while(*data!='\0'){
if(*data==find){
*data=replace;
}
data++;
}
return data;
}
In substitute() you return the pointer data that you have incremented in your while loop, so now it points to the terminating '\0' and that's what you printf().
You could either use a separate local variable for traversing the string, or you don't use the return value of substitute() at all and replace
printf("%s", substitute(arr, i, j));
by
substitute(arr, i, j);
printf("%s", arr );