language c char* starts from second element instead of first [duplicate] - c

This question already has answers here:
scanf() leaves the newline character in the buffer
(7 answers)
Closed 6 years ago.
We created this program in university that creates an array of characters by address in language c.
but the first element (char* str) output a weird space.
I saw some tutorials about arrays of characters where the first element is the first character we typed.
so why is this happening ? is their some situations where this happens ? if so how can i know if my string starts from the first or second element without using printf everytime ?
This is my program
#include<stdio.h>
#include<stdlib.h>
char* newStr(int n);
int length(char* str);
int main() {
int n,i;
printf("Number of characters \n");
scanf("%d",&n);
char* str = newStr(n);
char* c = malloc(n*sizeof(char)+1);
c=str;
// check that c[0]=' ' and c[n+1]=\0
for(i=0;i<=n+1;i++) printf("*(str+%d) = %c \n",i,*(c+i));
return 0;
}
char* newStr(int n) {
int i;
char* c;
c=malloc(n*sizeof(char)+1);
printf("Enter a word of %d characters \n",n);
for(i=0;i<=n;i++) {scanf("%c",(c+i));}
*(c+n+1)='\0';
return c;
}
int length(char* str) {
int i=0;
while(*(str+i)!='\0'){i++;}
return i-1;
}
and this is the output
Number of characters
5
Enter a word of 5 characters
hello
*(str+0) =
*(str+1) = h
*(str+2) = e
*(str+3) = l
*(str+4) = l
*(str+5) = o
*(str+6) =
The length of your string is 5
can someone explain it to me in simple termes as i'm quite new to c.
thanks in advance

Someone already answered in the comments that the scanf() function does not consume the trailing newline char.
So if the user presses "Enter" in their keyboard, and then a scanf() occurs in your code, that Enter press will be recorded.
Also I want to focus your attention in the newStr() function.
There you allocate space for a new string and store it in a dynamic array of characters, your char *c, and then return that pointer.
But in your main() you save the return value in str and, for some reason trying to copy it to another pointer(and doing it wrong by the way)?
char* str = newStr(n);
char* c = malloc(n*sizeof(char)+1);
c=str;
str is ALREADY a string you can use, no need to make another malloc on char *c. And when you write
c=str;
You are actually assigning to the char *c the address of str, not the values pointed by str, thus making this line of code:
char* c = malloc(n*sizeof(char)+1);
Completely useless, and error prone, because you will not be able to free that pointer anymore, having lost the address.
I don't know if I was clear...

As already mentioned, scanf("%d",&n) does not consume the new line character, but scanf("%d\n",&n) will.
BTW, just to present a short (but probably hacky) approach, which uses scanf("%20s",...), yet with variable width specifier instead of hardcoded 20:
int n;
char format[20];
scanf("%d\n",&n);
char *result = malloc((n+1) * sizeof(char));
sprintf(format, "%%%ds", n);
scanf(format, result);

Related

Why is the for printf in this C function not outputting the correct string?

I'm trying to write a function that outputs an input string 10 times. Here is the code.
#include <stdio.h>
int print10times(){
char input[] = "";
printf("Which string would you like to print 10 times? ");
scanf("%s", input);
for (int i=0; i<10; i++){
printf("%s\n", input);
}
return 0;
}
int main(){
print10times();
return 0;
}
The output I'm getting looks like this:
Which string would you like to print 10 times? Hello
H
H☺
H☻
H♥
H♦
H♣
H♠
H
H
H
Could someone let me know why this doesn't print "Hello" 10 times?
Thanks.
You declare char input[] = "";, which makes input a string of length 1 (containing only the terminating '\0'). It will not magically grow when you try to read more than zero characters into it, and instead you will access memory behind it (potentially destroying its content, crashing, or worse).
For example, declare it char input[80] = ""; instead, and you have space for up to 79 characters. This is still a potential issue, as your typed input could be longer, but it will work for up to 79 chars.
You have to give more space to input[] because char input[]=""; as you know that char take only 1 byte so in this case it reads only h of "hello" okk because there already a character called null character which also consume spaces if you want allocate memory at run time so you can use dynamic memory functions..
Overall just replace char input[]=""; with char input[50]; simple.....

strcmp return value is wrong (beginner) [duplicate]

This question already has answers here:
strcmp on a line read with fgets
(6 answers)
Closed 5 years ago.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void getSentence(char userSentence[]);
int breakSentence_andCompare(char userSentence[] , char compareSentence[]);
#define MAX_SENTENCE 100
int main()
{
int len = 0;
char userSentence[MAX_SENTENCE] = {'o','k',0};
char compareSentence[MAX_SENTENCE] = {'o',0};
getSentence(userSentence);
len = breakSentence_andCompare(userSentence,compareSentence);
}
/*
This function is asking the user to input info.
input:user input string array - char userSentence[].
output:none.
*/
void getSentence(char userSentence[])
{
printf("Hello And Welcome To The Palindrome Cheker Made By xXTH3 SKIRT CH4S3RXx");
printf("\nPlease Enter A Sentence: ");
fgets(userSentence,MAX_SENTENCE,stdin);
}
/*
This function takes the input of the user and input it into another string backwards.
input:user input string array - char userSentence[], backward user input string array - char compareSentence[].
output:strcmp value.
*/
int breakSentence_andCompare(char userSentence[] , char compareSentence[])
{
int i = 0;
int z = 0;
int len = 0;
int cmp = 0;
len = strlen(userSentence);
len -= 1;
for (i = len ; i >= 0 ; i--)
{
compareSentence[z] = userSentence[i];
printf("%s",compareSentence);
z++;
}
printf("\nuser: %s! compare: %s!",userSentence,compareSentence);
cmp = strcmp(userSentence,compareSentence);
printf("\n%d",&cmp);
return cmp;
}
This program checks if inputted string is palindrome,
To simply explain how it works:
It takes user input - String.
It Takes the user string and input is backwards in another string.
It compares the strings.
I have a really strange problem in the function and that's the strcmp return value. For some reason, when both strings have the same characters like ABBA the strcmp will return that the value of one of them is bigger. I'd really love to know what is the problem and how can I fix it.
P.S
When I were searching the problem I thought that it might be connected to fact that the user input string might contain \n from the enter key; is that possible?
And please understand that this isn't a whole code. The code is missing the output part.
The problem is occurring because of trailing \n (newline) character in user input string.
fgets()
The fgets() function shall read bytes from stream into the array
pointed to by s, until n-1 bytes are read, or a is read
and transferred to s, or an end-of-file condition is encountered.
The string is then terminated with a null byte. [EMPHASIS MINE]
So, a newline character makes fgets stop reading, but it is considered a valid character by the function and included in the input string.
Say, user input string is "ABBA". So, after entering the input the content of userSentence will be "ABBA\n".
In your program, you are reversing the input string and comparing it with the original input string.
After reversing, the content of compareSentence will be "\nABBA".
The content of both the strings are not same and the strcmp() will return non zero value as the comparison result.
There are various ways of removing trailing \n (newline) character from fgets() input. Check this.
Since you are a beginner, so one suggestion to you - Don't ignore the compiler warning('s).
For the statement -
printf("\n%d",&cmp);
You must be getting a warning message during compilation of your program.
You should try to identify the cause of warning message('s) and should resolve them.
There are much better ways to find out the whether a string is palindrome or not but since you are a beginner, your start is good. Happy Learning.. :)

How to correctly input a string in C

I am currently learning C, and so I wanted to make a program that asks the user to input a string and to output the number of characters that were entered, the code compiles fine, when I enter just 1 character it does fine, but when I enter 2 or more characters, no matter what number of character I enter, it will always say there is just one character and crashes after that. This is my code and I can't figure out what is wrong.
int main(void)
{
int siz;
char i[] = "";
printf("Enter a string.\n");
scanf("%s", i);
siz = sizeof(i)/sizeof(char);
printf("%d", siz);
getch();
return 0;
}
I am currently learning to program, so if there is a way to do it using the same scanf() function I will appreciate that since I haven't learned how to use any other function and probably won't understand how it works.
Please, FORGET that scanf exists. The problem you are running into, whilst caused mostly by your understandable inexperience, will continue to BITE you even when you have experience - until you stop.
Here is why:
scanf will read the input, and put the result in the char buffer you provided. However, it will make no check to make sure there is enough space. If it needs more space than you provided, it will overwrite other memory locations - often with disastrous consequences.
A safer method uses fgets - this is a function that does broadly the same thing as scanf, but it will only read in as many characters as you created space for (or: as you say you created space for).
Other observation: sizeof can only evaluate the size known at compile time : the number of bytes taken by a primitive type (int, double, etc) or size of a fixed array (like int i[100];). It cannot be used to determine the size during the program (if the "size" is a thing that changes).
Your program would look like this:
#include <stdio.h>
#include <string.h>
#define BUFLEN 100 // your buffer length
int main(void) // <<< for correctness, include 'void'
{
int siz;
char i[BUFLEN]; // <<< now you have space for a 99 character string plus the '\0'
printf("Enter a string.\n");
fgets(i, BUFLEN, stdin); // read the input, copy the first BUFLEN characters to i
siz = sizeof(i)/sizeof(char); // it turns out that this will give you the answer BUFLEN
// probably not what you wanted. 'sizeof' gives size of array in
// this case, not size of string
// also not
siz = strlen(i) - 1; // strlen is a function that is declared in string.h
// it produces the string length
// subtract 1 if you don't want to count \n
printf("The string length is %d\n", siz); // don't just print the number, say what it is
// and end with a newline: \n
printf("hit <return> to exit program\n"); // tell user what to do next!
getc(stdin);
return 0;
}
I hope this helps.
update you asked the reasonable follow-up question: "how do I know the string was too long".
See this code snippet for inspiration:
#include <stdio.h>
#include <string.h>
#define N 50
int main(void) {
char a[N];
char *b;
printf("enter a string:\n");
b = fgets(a, N, stdin);
if(b == NULL) {
printf("an error occurred reading input!\n"); // can't think how this would happen...
return 0;
}
if (strlen(a) == N-1 && a[N-2] != '\n') { // used all space, didn't get to end of line
printf("string is too long!\n");
}
else {
printf("The string is %s which is %d characters long\n", a, strlen(a)-1); // all went according to plan
}
}
Remember that when you have space for N characters, the last character (at location N-1) must be a '\0' and since fgets includes the '\n' the largest string you can input is really N-2 characters long.
This line:
char i[] = "";
is equivalent to:
char i[1] = {'\0'};
The array i has only one element, the program crashes because of buffer overflow.
I suggest you using fgets() to replace scanf() like this:
#include <stdio.h>
#define MAX_LEN 1024
int main(void)
{
char line[MAX_LEN];
if (fgets(line, sizeof(line), stdin) != NULL)
printf("%zu\n", strlen(line) - 1);
return 0;
}
The length is decremented by 1 because fgets() would store the new line character at the end.
The problem is here:
char i[] = "";
You are essentially creating a char array with a size of 1 due to setting it equal to "";
Instead, use a buffer with a larger size:
char i[128]; /* You can also malloc space if you desire. */
scanf("%s", i);
See the link below to a similar question if you want to include spaces in your input string. There is also some good input there regarding scanf alternatives.
How do you allow spaces to be entered using scanf?
That's because char i[] = ""; is actually an one element array.
Strings in C are stored as the text which ends with \0 (char of value 0). You should use bigger buffer as others said, for example:
char i[100];
scanf("%s", i);
Then, when calculating length of this string you need to search for the \0 char.
int length = 0;
while (i[length] != '\0')
{
length++;
}
After running this code length contains length of the specified input.
You need to allocate space where it will put the input data. In your program, you can allocate space like:
char i[] = " ";
Which will be ok. But, using malloc is better. Check out the man pages.

Need help finding bug, if string input is composed all of same character one output character is corrupt

reverser() reverses a cstring (not in place). 99% of the time it works but some input corrupts it for example it appears if aStr2[] is assigned a string made up of the same character it will have an error.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* reverser(const char *str);
int main()
{
char aStr[] = "aaa";
char aStr2[] = "cccccc";
printf("%s %s", aStr, aStr2);
char* tmp = reverser(aStr2);//tmp now has garbage
printf("\n%s", tmp);
printf(" %s", aStr2);
return 0;
}
char* reverser(const char *str)
{
char* revStr = (char*)malloc(strlen(str));
int i;
for(i = strlen(str)-1; i >= 0; i--)
{
revStr[strlen(str)-1-i] = str[i];
}
return revStr;
}
Gives
aaa cccccc
cccccc9 cccccc
Process returned 0 (0x0) execution time : 0.068 s
Press any key to continue
Notice the 9 that shouldn't be there.
Change this malloc to strlen(str) + 1 , plus 1 for '\0'
char* revStr = (char*)malloc(strlen(str) + 1);
and after the for loop
revStr[strlen(str)+1] = '\0';
Your problem is that you don't put the string terminator in your reversed string. All strings in C are actually one extra character that isn't reported by strlen, and that is the character '\0' (or plain and simple, a zero). This tells all C functions when the string ends.
Therefore you need to allocate space for this extra terminator character in your malloc call, and add it after the last character in the string.
There are also a couple of other problems with your code, the first is that you should not cast the return of malloc (or any other function returning void *). Another that you have a memory leak in that you do not free the memory you allocate. This last point doesn't matter in a small program like the one you have here, but will be an issue in larger and longer running programs.
You haven't null-terminated your reversed string. You need to set the final index of revStr[] to 0.

printf() isn't being executed

I wanted to write a program which counts the occurrences of each letter in a string, then prints one of each letter followed by the count for that letter.
For example:
aabbcccd -
Has 2 a, 2 b, 3 c, and 1 d
So I'd like to convert and print this as:
a2b2c3d1
I wrote code (see below) to perform this count/conversion but for some reason I'm not seeing any output.
#include<stdio.h>
main()
{
char array[]="aabbcccd";
char type,*count,*cp=array;
while(cp!='\0'){
type=*cp;
cp++;
count=cp;
int c;
for(c=1;*cp==type;c++,cp++);
*count='0'+c;
}
count++;
*count='\0';
printf("%s",array);
}
Can anyone help me understand why I'm not seeing any output from printf()?
char array[]="aabbcccd";
char type,*count,*cp=array;
while(cp!='\0'){
*cp is a pointer it's pointing to the address of the start of the array, it will never be == to a char '\0' so it can't leave the loop.
You need to deference the pointer to get what it's pointing at:
while(*cp != '\0') {
...
Also, you have a ; after your for loop, skipping the contents of it:
for(c=1;*cp==type;c++,cp++); <-- this ; makes it not execute the code beneath it
After fixing both of those problems the code produces an output:
mike#linux-4puc:~> ./a.out
a1b1c2cd
Not the one you wanted yet, but that fixes your problems with "printf not functional"
Incidentally, this code has a few other major problems:
You try to write past the end of the string if the last character appears once (you write a '1' where the trailing '\0' was, and a '\0' one character beyond that.
Your code doesn't work if a character appears more than 9 times ('0' + 10 is ':').
Your code doesn't work if a character appears more than 2 times ("dddd" doesn't become "d4"; it becomes "d4dd").
Probably line-buffering. Add a \n to your printf() formatting string. Also your code is very scary, what happens if there are more than 9 of the same character in a row?
1) error correction
while(*cp!='\0'){
and not
while(cp!='\0'){
2) advice
do not use array[] to put in your result user another array to put in your rusel it's more proper and eay
I tried to solve your question quickly and this is my code:
#include <stdio.h>
#define SIZE 255
int main()
{
char input[SIZE] = "aabbcccd";/*input string*/
char output[SIZE]={'\0'};/*where output string is stored*/
char seen[SIZE]={'\0'};/*store all chars already counted*/
char *ip = input;/*input pointer=ip*/
char *op = output;/*output pointer = op*/
char *sp = seen;/*seen pointer=sp*/
char c,count;
int i,j,done;
i=0;
while(i<SIZE && input[i]!='\0')
{
c=input[i];
//don't count if already searched:
done=0;
j=0;
while(j<SIZE)
{
if(c==seen[j])
{
done=1;
break;
}
j++;
}
if(done==0)
{//if i never searched char 'c':
*sp=c;
sp++;
*sp='\0';
//count how many "c" there are into input array:
count = '0';
j=0;
while(j<SIZE)
{
if(ip[j]==c)
{
count++;
}
j++;
}
*op=c;
op++;
*op=count;
op++;
}
i++;
}
*op='\0';
printf("input: %s\n",input);
printf("output: %s\n",output);
return 0;
}
It's not a good code for several reasons(I don't check arrays size writing new elements, I could stop searches at first empty item, and so on...) but you could think about it as a "start point" and improve it. You could take a look at standard library to copy substring elements and so on(i.e. strncpy).

Resources