preprocessor directive not working - c

I made a program which removes spaces and makes a string upper case by preprocessor directives .its not changing to uppercase
#include <stdio.h>
#include <conio.h>
# define TOUPPER(x) (x-32)
void main(void)
{
int i,j;
char str[100],*p;
clrscr();
printf("Enter the string:\n");
gets(str);
for(i=0; ;i++)
{
if(str[i]=='\0')
break;
if(str[i]==' ')
{
for(j=i; ;j++)
{
str[j]=str[j+1];
if(str[j]=='\0')
break;
}
}
if(str[i]<='a'||str[i]>='z')
{
*p=str[i];
TOUPPER('p');
}
}
puts(str);
getch();
}

Your TOUPPER('p') does exactly what it should, nothing. You're subtracting 32 from the numeric value of 'p' and then throwing it away. Note that I'm referring to 'p' the character, not p the pointer.

Problem is wrong range condition, Macro call with constant argument and you are not assigning the value back.
if(str[i]<='a'||str[i]>='z')
{
*p=str[i];
TOUPPER('p');
}
Correction:
if(str[i]>='a'||str[i]<='z')
{
str[i] = TOUPPER(str[i]);
}

Perhaps this is what you wanted:
str[i]=TOUPPER(str[i])
(And don't mess around with those pointer p)

Its because you do
TOUPPER('p');
and it is defined as
(x-32)
This changes 'p' to upper-case but don't save it.
You need to change you define like this
#define TOUPPER(x) ((*x)=((*x)-32))
just do call it like this:
TOUPPER(p);

This isn't what you're asking, but please note you have a serious pointer error in your program:
char str[100],*p;
...
if(str[i]<='a'||str[i]>='z')
{
*p=str[i];
TOUPPER('p');
}
The pointer p is uninitialized (can be pointing to anywhere in memory), and you are assigning the character str[i] to that pointer's memory location. p might be equal to 0x00000000 or 0xCDCDCDCD or something else, but in any case you are writing str[i] to that location without initializing p to an appropriate address.
If you feel you must use pointers, you could do it this way (still doesn't fix the range issue that others mentioned, the <= and >= are backwards):
if (str[i]<='a'||str[i]>='z')
{
p=&str[i]; // p now points to the address of str[i]
*p = TOUPPER(*p); // p = the address, *p = the contents of that address
}

Don't believe that using preprocessor macros is always faster than using the functions from <ctype.h>. It is highly probable that these functions are in fact implemented as preprocessor macros themselves. Just write code that is easy to understand, and only "optimize" it if it is necessary.
#include <conio.h>
#include <ctype.h>
#include <stdio.h>
#include <string.h>
static void
str_toupper(char *str)
{
char *p;
for (p = str; *p != '\0'; p++) {
if (isspace((unsigned char) *p)) {
memmove(p + 0, p + 1, strlen(p) - 1);
}
*p = toupper((unsigned char) *p);
}
}
int main(void)
{
char str[100];
clrscr();
printf("Enter the string:\n");
if (fgets(str, sizeof str, stdin) == NULL)
return 0;
str_toupper(str);
printf("%s\n", str);
getch();
return 0;
}

Related

'SER_' or '_' character appearing in end of (string)output in c

I am trying to print each word in a single line of a given sentence. It worked perfectly fine but a '_' appears in end of line. please help me with it and also proper manar to write it.
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
int main() {
char *s,i,check=0;
s = malloc(1024 * sizeof(char));
scanf("%[^\n]", s);
s = realloc(s, strlen(s) + 1);
for(i=0;i<1024;i++ ||check<=2)
{
if(*(s+i)!=' ')
{
printf("%c",*(s+i));
check=0;
}
else
{
printf("\n");
check++;
}
// fflush(stdin);
}
return 0;
}
Output:
dkf fja fjlak d
dkf
fja
fjlak
d SER_
Output2:
-for(i=0;i<20;i++ ||check<=2)-
hello I am suraj Ghimire
hello
I
am
suraj
Ghi
I am not sure your code works as you say..
The type of i is not a char *, so it should be int.
You process the input string without considering the NULL terminating char, which leads to a lot of garbage prints.
You do not release allocated memory.
I suggest this slightly modified version:
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
int main() {
char *s, *p;
/* Allocate a new string and verify the allocation has succeeded. */
s = malloc(1024 * sizeof(char));
if (!s) {
printf("malloc failed\n");
return 1;
}
/* Read from user. */
scanf("%[^\n]", s);
/* Work on a copy of `s` (must simpler and faster than a indexed access). */
p = s;
while (*p) {
if (*p != ' ') {
printf("%c",*p);
}else{
printf("\n");
}
p++;
}
free(s);
return 0;
}
Example output:
$ ./a.out
abc def gh i j kmlm opqrst
abc
def
gh
i
j
kmlm
opqrst
EDIT: As requested by the OP, further details regarding the NULL terminating char.
By convention, strings (array of characters) end with a specific character which we call the NULL terminating char. This character is 0 and marks the end of the string data.
In your example, the buffer which store the string is dynamically allocated in RAM. If you do not check for the NULL terminating character of the string, then you keep processing data as if it is part of the string (but it is not).
Going beyond this character make you access the following memory data (which is part of your program RAM data). Since these data can be anything (ranging from 0 to 255), printing them may lead to "gibberish" because they may not be printable and are definitely not consistent with your string.
In the "best" case the program halts with a "segmentation fault" because you are accessing a memory region you are not allowed to. In the "worst" case you print a lot of things before crashing.
This is typically called a data leak (whether it is RAM or ROM) because it exposes internal data of your program. In the specific case of your example there no sensitive data. But! Imagine you leak passwords or private keys stored in your program .. this can be a severe security issue!
There are a couple issues with your code.
Firstly, you need to check that the for loop does not exceed the bounds of the string.
Your for loop is always set to true because the logical OR operator || has a higher precedence than the comma operator. Because of this the loop will always run unless it gets stopped with break
Lastly your check is never reset to 0 after it reaches a value of 2.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main() {
char *s,i,check=0;
s = malloc(1024 * sizeof(char));
scanf("%[^\n]", s);
s = realloc(s, strlen(s) + 1);
for(i=0; i<strlen(s); i++) {
if(*(s+i) != ' ') {
printf("%c",*(s+i));
check=0;
} else {
printf("\n");
check++;
if (check > 2) break;
}
}
return 0;
}
Output:
Hello, this is a test
Hello,
this
is
a
test
for(i=0;i<1024;i++ ||check<=2)
There are two issues. One is length of string won't always be 1024, so it might be good to determine the length of string before print the string. The other is check<=2, which have to put in the second part of the for loop, so the test will be evaluated. Also it is better to calculate the length of string once. So I store the length of string in len.
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char *s, i, check = 0;
s = malloc(1024 * sizeof(char));
scanf("%[^\n]", s);
s = realloc(s, strlen(s) + 1);
size_t len = strlen(s);
for (i = 0; i < len || check <= 2; i++) {
if (*(s + i) != ' ') {
printf("%c", *(s + i));
check = 0;
} else {
printf("\n");
check++;
}
// fflush(stdin);
}
return 0;
}

does the pointer reallocate memory as it increments?

how can i stop *str from filling memory that i didnt give to it, without having to add an ending condition which in this case is : i <= n
do{
//instructions;
} while (... && i <= n);
in this exemple i reserved only 3 bytes of memory to *str but when i run my code and input more than 3 characters it still works... how does that happen shouldnt it give an error cuz there isnt enough memory for the rest of the characters ? what if the selected empty adresses were xxxxx1 xxxxx2 xxxxx3 and then xxxxx4 is full will it stop and output only the 3 characters without an error ?
P.s : I am aware of the function gets() but i dont want to use it because it reallocates memory. i thought that by entering character by character i will solve the problem and stop the user from filling the pointer because this time there is no memory reallocation and *str only has 3 blocks of memory so the rest will go to the buffer and *str will stop at *(str + 2)
hope u understood the problem and thank u for answering
#include <stdio.h>
#include <string.h>
#include <malloc.h>
int main()
{
int i = -1, n = 3;
char *str = (char *)malloc(n*sizeof(char));
printf("Enter a string: ");
do
{
i++;
str[i] = getchar();
} while (str[i] != '\n' && i < n);
str[i] = '\0';
printf("Entered string is: %s", str);
return 0;
}
C doesn't perform any type of bounds checking on arrays or allocated memory. That's part of what makes it fast.
That also means that reading or writing past the end of an array causes undefined behavior which basically means there's no guarantee what the program will do. The language trusts you to do the proper thing, so it's up to you to ensure that you don't do something you shouldn't.
Also, gets doesn't reallocate memory. In fact, it shouldn't be used at all specifically because it doesn't perform any bounds checking.
Your example doesn't work if the input string is longer than two characters since it then tries to write beyond the array. What will happen when you try to write outside of the array is undefined, which means that it may work by pure chance under some circumstances. Try this safe function instead which always reads the entire line and truncates the result if necessary:
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void ReadLine(char result[], int resultLen)
{
int ch, i;
assert(resultLen > 0);
i = 0;
ch = getchar();
while ((ch != '\n') && (ch != EOF)) {
if (i < resultLen - 1) {
result[i] = ch;
i++;
}
ch = getchar();
}
result[i] = '\0';
}
int main(void)
{
int n = 3;
char *str = malloc(n);
printf("Enter a string: ");
ReadLine(str, n);
printf("Entered string is: %s\n", str);
free(str);
return 0;
}

Manipulation array in function - c - Segmentation fault

So I started to learn how to code a few weeks ago, and this site helped me so much, thank you for that. But this time I got stuck and canĀ“t really figure out why...Hope you can help me.
Basically I have a function prototype I have to use in my program and I have my troubles with it. The function should receive a string and then only copy every second char of that string and return the result...
This is what I've got so far:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define max_size 1000
char * everySecondChar(char * dest, char * input);
int main() {
char inputstr[max_size] = {0};
char *input[max_size] = {0};
char *dest[max_size] = {0};
char temp[max_size] = {0};
int i = 0;
while (fgets(inputstr, max_size, stdin) != NULL)
{
input[i] = strndup(inputstr, max_size);
strcat(temp,inputstr);
i++;
}
input[0] = strndup(temp, max_size);
printf("Inputted text:\n%s", *input);
printf("\n");
printf("\n");
printf("Resulting string:\n");
everySecondChar(*dest, *input);
printf("%s", *dest);
return 0;
}
char * everySecondChar(char * dest, char * input)
{
int i = 0;
for(i = 0; i < max_size; i+=2) {
strcat(dest,input);
}
return dest;
}
I know this is probably a 1-min challenge for the most of you, but I am having my troubles whenever I see those nasty * in a function prototype :(
Congrats on getting started with programming!
To your question: there's quite a few things that could be addressed, but since there seems to be some more basic confusion and misunderstanding, I'll address what makes sense given the context of your issue.
First, you're using strcat which concatenates strings (e.g. adds to the string), when you just need simple character assignment.
Next, you have a lot of pointers to arrays and there seems to be some confusion regarding pointers; in your main function, you don't need all of the temporary variables to do what you're wanting.
You could have simply:
char inputstr[MAX_SIZE] = {0};
char dest[MAX_SIZE] = {0};
You could have less (realistically) but we'll stick with the basics for now.
Next, you're looping to get user input:
while (fgets(inputstr, max_size, stdin) != NULL)
{
input[i] = strndup(inputstr, max_size);
strcat(temp,inputstr);
i++;
}
Here, you don't check if i exceeds max_size which your input variable has been allocated for; if i exceeds max_size when you go to assign input[i] to the memory location returned by strndup (which calls malloc), you are writing beyond your memory bounds, which is also known as a buffer overflow. This is potentially where your segmentation fault is happening. You could also have some issues when you do strcat(temp,inputstr); since strcat:
Appends a copy of the source string to the destination string. The terminating null character in destination is overwritten by the first character of source, and a null-character is included at the end of the new string formed by the concatenation of both in destination.
If you're simply just trying to get what the user entered, and print every 2nd character with your function, you don't need to loop:
if (fgets(inputstr, MAX_SIZE, stdin) != NULL) {
everySecondChar(dest, inputstr);
printf("Inputted text:\n%s\n\nResulting string:\n%s\n", inputstr, dest);
}
Lastly, in your everySecondChar function, you're using strcat again when all you need to do is simple assignment (which does a 'copy'):
char * everySecondChar(char * dest, char * input)
{
int i, j;
for(i = 0, j = 0; i < MAX_SIZE; ++i, ++j) {
if (input[i] == 0) break; // end if string?
dest[j] = input[i++];
}
return dest;
}
Putting all of it together, you get:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAX_SIZE 1000
char * everySecondChar(char * dest, char * input);
int main(void)
{
char inputstr[MAX_SIZE] = {0};
char dest[MAX_SIZE] = {0};
printf("Enter some text: ");
if (fgets(inputstr, MAX_SIZE, stdin) != NULL) {
everySecondChar(dest, inputstr);
printf("Inputted text:\n%s\n\nResulting string:\n%s\n", inputstr, dest);
}
return 0;
}
char * everySecondChar(char * dest, char * input)
{
int i, j;
for(i = 0, j = 0; i < MAX_SIZE; ++i, ++j) {
if (input[i] == 0) break; // end if string?
dest[j] = input[i++];
}
return dest;
}
That aside, I'll address some other things; typically if you have a constant value, like your max_size variable, it's considered "best practice" to capitalize the entire thing:
`#define MAX_SIZE 1000`
I am having my troubles whenever I see those nasty * in a function prototype :(
Those nasty *'s in your function prototype (and variable declarations) are known as a pointer qualifier; it indicates that the type of the variable is a pointer to the type specified. A pointer isn't something to be scared of, you're learning C, it's highly important you understand what a pointer is and it's utility.
I won't dive into all of the specificities of pointers, aliases, etc. etc. since that is beyond the scope of this Q&A, but WikiBooks has a great intro and explanation covering a lot of those concepts.
Hope that can help!

scanf catches char type string with \0 and bunch of zeros after in C

I'm working on enumerations in C and can't find the source of problem in the following example that, the output is always "Sorry!":
#include <stdio.h>
#include <stdlib.h>
typedef enum
{
summer, winter, fall, spring
} season;
void printPhrase (season s);
int main(void)
{
printf("What's your prefered season? ");
char seasonHold[10], seasonHold2[10];
scanf("%s", seasonHold);
for (int n = 0; n < strlen(seasonHold); n++)
{
if (n != '\0')
seasonHold2[n] = seasonHold[n];
}
printPhrase (*seasonHold2);
return 0;
}
void printPhrase (season s)
{
if (s == summer)
printf("It's hot out!\n");
else if (s == fall)
printf("It's getting cooler!\n");
else if (s == winter)
printf("Should be really cold!\n");
else if (s == spring)
printf("It should be lovely outside!\n");
else
printf("Sorry!\n");
}
The problem is whatever input I enter, there's always one output: Sorry!
Thanks.
Also, this can solve the matter:
I could manage it by changing main function into following:
int main(void)
{
printf("What's your prefered season? ");
char seasonHold[10];
scanf("%s", seasonHold);
if (seasonHold[0] == 's')
printPhrase (summer);
else if (seasonHold[0] == 'f')
printPhrase(fall);
else if (seasonHold[1] == 'p')
printPhrase(spring);
else if (seasonHold[0] == 'w')
printPhrase(winter);
return 0;
}
Enums are like constant integers. Here: summer=0, winter=1,...
seansonhold is a char*. By dereferencing it you get a char. This char will then be converted to a 'season' type because char->int does not give compiler errors.
So you basically test here if the first byte of your char array is equal to 0,1,2..
If you are sure seasonHold is null-terminated (it will be here), you can use a pointer and while loop to accomplish what you want:
char *ptr = seasonHold;
n = 0;
while (*ptr++) { /* same as saying while (*ptr++ != '\0') */
seasonHold2[n] = seasonHold[n]; /* could also do: seasonHold2[n] = *ptr; */
n++;
}
seasonHold2[n] = 0; /* null-terminate */
Additionally, if you would like to dynamically allocate seasonHold2, you can simply declare it as a pointer, include string.h and use strdup to copy seasonHold to seasonHold2, e.g.:
#include <string.h>
...
char *seasonHold2;
...
seasonHold2 = strdup (seasonHold);

Why is c not returning my string?

I don't understand why the program below returns "z#" as string. But when I put a printf("%s \n",""); before that, then it returns "11110111" (as aspected).
Can anybody help me to understand this behaviour?
Many thanks in advance!
Please find my whole program posted below:
#include <stdio.h>
char * bin2str(unsigned char bin) {
char str[] = "00000000";
int i;
for (i=7; i>=0; i--) {
if ((bin%2)==0) {
str[i] = '0';
} else {
str[i] = '1';
}
bin = bin >> 1;
}
return ((char *) str);
}
int main() {
unsigned char testChar;
testChar |= 0b11110111;
printf("Let us test binary to string: \n\n \n");
//printf("%s \n","");
printf("%s \n", bin2str(testChar)); //now it returns rubbish, but when the previous line is uncommented it turns out to be working correctly. Why?
return 0;
}
You are returning the local variable str from the function bin2str which is undefined behaviour. Instead you could copy it using strdup() (or its equivalent using malloc() + strcpy()).
char *str = strdup("00000000");
and return it.
Don't forget to free() it!
You are generating a string as a local variable inside bin2str(). That string will be located in stack space while bin2str() is executing. As soon as the function returns, the stack space is no longer valid, and the memory pointed by str will contains whether the program puts in the stack between the return from the call to bin2str() and the call to printf() where you intend to print the contents of str.
Alternatives:
Declare str as static. This way, str won't be placed in stack space and its contents will be available even after the function ends. Beware! as this solution is not thread safe.
Change your prototype so it accepts a second argument, which will be the address of a string that the caller will have to provide, to which bin2str() will write the binary representation of the number.
Thanks you all for your feedback. Wow, that was fast!
It was my first post.
I made the changes. Please find the correct functioning program below (without compile warnings):
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char * bin2str(unsigned char bin) {
char *str = strdup("00000000");
int i;
for (i=7; i>=0; i--) {
if ((bin%2)==0) {
str[i] = '0';
} else {
str[i] = '1';
}
bin = bin >> 1;
}
return ((char *) str);
free(str);
}
int main() {
unsigned char testChar;
testChar |= 0b11110111;
printf("Let us test binary to string: \n\n \n");
printf("%s \n", bin2str(testChar));
return 0;
}

Resources