Only first char of user input used in array - c

I am writing some code for a nanokernel, which means I can't use the standard library, although I have implemented functions for printing strings and getting chars from the keyboard.
Right now I have the program set up to take chars from the keyboard and put them into an array. The string is then printed out. I expect the string printed out to look exactly like what was inputted by the user.
The issue is that it seems that the only char being put into the string is the first char inputted on the keyboard.
here is the relevant code for putting the chars into an array:
void stringin(char str[]) { // takes a string, puts it in str
int i = 0;
for (i = 0; str[i] != '\n' && str[i] != '\033';) {
str[i] = getch();
if (str[i] != '\n' && str[i] != '\033') {
i++;
}
calctime(1000000); // waits for a bit so that we don't flood the array
}
if (str[i] == '\n') newline(1);
str[i++] = '\0';
}
I have used both a printing function and a strcmp() implementation to test the contents of the string, so nothing seems to be going wrong with printing the string.

Based on the comments, str is passed to stringin with the buffer uninitialized.
Since the following loop terminates based on the value of str[i] before str[i] is actually initialized, the results are undefined.
for (i = 0; str[i] != '\n' && str[i] != '\033';) {
str[i] = getch();
....

Related

What's wrong with this string checking program?

I want to make this program only English in the string, but when the end of the string ends in English, another strange word is added. Why is that?
int main(void)
{
char line[100];
char line2[100];
printf("Please enter a string: ");
gets_s(line, sizeof(line));
int k = 0;
for(int i = 0; line[i] != '\0'; ++i) {
while(line[i] >= 'A'&& line[i] <= 'z') {
line2 [k++] = line[i++];
}
}
line2[k] = '\0';
printf("string: %s\n", line2);
return 0;
}
for(int i = 0; line[i] != '\0'; ++i) {
while(line[i] >= 'A'&& line[i] <= 'z') {
line2 [k++] = line[i++];
}
}
replacing the for loop with a while loop...
int i = 0;
while (line[i] != '\0') {
while (line[i] >= 'A' && line[i] <= 'z') {
line2 [k++] = line[i++];
}
i++;
}
So, here you can see if the inner while goes to the '\0' i gets incremented past the terminating zero byte.
The basic problem is that you put responsibility for incrementing i in two different places. As a result, it can get incremented more than you want -- for example, so as to skip over the string terminator.
It appears to me that you have caused this problem for yourself by making the code more complicated than it needs to be. Why use a two-loop nest to iterate over a single string? In fairness, there are indeed potential reasons to do that, but none of them appear to be in evidence here. I suggest changing the inner while loop to an if statement, and not incrementing i within:
for (int i = 0; line[i] != '\0'; ++i) {
if (line[i] >= 'A' && line[i] <= 'z') {
line2[k++] = line[i];
}
}
Note how there is only one place where i is incremented in that variation.
Note also that there may be characters that satisfy c >= 'A' && c <= 'z' but are not letters. I say "may" because C is not specific to a particular character set or encoding, but in practice, it is virtually certain that there are non-letter characters in that range on your implementation. Perhaps isalpha((unsigned char) line[i]) would be a better fit, though it is not, by itself, without character set related issues.

Find vowels in a string

Given below is my code for finding vowels in a given string:
#include <stdio.h>
#include <string.h>
int main() {
char str[100];
int i, str_length;
//scanf("%[^\n]%*c", &str[100]);
fgets(str, sizeof(str), stdin);
str_length = strlen(str);
for (i = 0; i < str_length; i++) {
if (str[i] == 'a' || str[i] == 'e' ||
str[i] == 'i' || str[i] == 'o' ||
str[i] == 'u' || str[i] == 'A' ||
str[i] == 'E' || str[i] == 'I' ||
str[i] == 'O' || str[i] == 'U')
{
printf("Vowels in the string are: %c \n", str[i]);
}
}
return 0;
}
I just wanna know, why scanf("%[^\n]%*c",&str[100]) is not working in my code?
cause I tried executing my program multiple times using scanf but it didn't worked.
And after using fgets I got the desired output.
So, can anyone help me to understand, where I am wrong!!
In the scanf function call, this &str[100] takes a pointer to str, makes it point to the element with the index 100 (which is past the end of the array), dereferences it and then takes the address of that (non-existing) element. This, most likely, leads to an attempt to an invalid write, which is probably caught by the operating system which terminates your program. In any case, the string is not written to the correct location.
Instead, you want the argument to point to the memory location of the first element of str, i.e.:
scanf("%[^\n]%*c", str);
That said, using fgets is better as it accepts an argument for the size which prevents buffer overflows. A size can also be given to scanf, but since it is part of the format specifier it cannot be a variable; only a hardcoded constant:
scanf("%99[^\n]%*c", str);
Note that this is for 99 elements, as there needs to be room for the null-terminator (\0) as well. See here for more info on scanf. But again, using fgets is less error prone and to be preferred.
Some additional advice:
The typical signature of the main function, using no parameters, is int main(void).
The scanf version fails if the input is a single newline character. Both versions fail on no input. It is always a good idea the check the return values of input (and output) functions.
Inside of the for-loop, you could create a copy of the current character converted to lowercase using the tolower function, and then perform only the lowercase comparisons. I.e.:
for (i = 0; i < str_length; i++) {
char ch = tolower(str[i]);
if (ch == 'a' || ch == 'e' || ch == 'i' || ch == 'o' || ch == 'u')
printf("Vowels in the string are: %c \n", str[i]);
}
Another option is to replace the comparisons in the if-statement with a call to strchr, which makes the program a bit more generic and scalable (one string is more easily changed than multiple comparisons):
char ch = tolower(str[i]);
if (strchr("aeiou", ch) != NULL)
printf("Vowels in the string are: %c \n", str[i]);

Simple Caesar Cipher Program in C

Hey guys I'm starting to learn C, and I was asked to code a program specifically, a caesar cipher (so, the idea is to replace any letter in the message by a letter three positions down the alphabet.)
My implementation should read a line of text and then either performs encryption or decryption, depending on the first character read. If the first character is $, then I'm supposed to encrypt the rest of the line, and precede the output by the character ?. If the first character is ?, then I'm supposed to decrypt the rest of the line, and precede my output by the character $.
So for example: ?Wr eh, ru qrw wr eh
the output should be: $To be, or not to be
and vice versa.
So this is my code so far:
#include <stdio.h>
int main(void){
char code[100], ch;
int i;
scanf("%s", &code);
if(code[0] == '$'){
for(i = 0; code[i] != '\0'; ++i){
ch = code[i];
if(ch >= 'a' && ch <= 'z'){
ch = ch + 3;
if(ch > 'z'){
ch = ch - 'z' + 'a' - 1;
}
code[i] = ch;
}
else if(ch >= 'A' && ch <= 'Z'){
ch = ch + 3;
if(ch > 'Z'){
ch = ch - 'Z' + 'A' - 1;
}
code[i] = ch;
}
}
printf("?%s\n", code);
return 0;
}
}
But the problem is, it returns the first character and stops whenever there are space.
Like for example I enter: $To be it outputs to: ?$To
Can someone please help me figure out what I'm doing wrong?
Here's a sample using getchar() to get you started:
#include <stdio.h>
int main() {
int ch; // Either EOF or one of the chars in 0-255
while ((ch = getchar()) != EOF) {
if ('A' <= ch && ch <= 'Z') {
int offset = ch - 'A';
printf("%c", 'a' + offset);
} else {
printf("%c", ch);
}
}
}
Now, this code isn't perfect in a lot of ways, but it does demonstrate how to use getchar(). Every time getchar() is called, it fetches the next char from standard input and returns it as an int. That's because when the input is over, it returns the special value EOF, which is outside the range of char.
The while loop here is a common idiom. When execution reaches the loop, it first has to call getchar(), whose result is stored into ch. Then it checks whether ch is EOF. If not, then the loop processes the character that was read. Otherwise, it exits and the program ends.
The body of the loop prints every character it sees, while converting the uppercase letters to lowercase.

why below code is giving garbage value?

why following code is giving garbage value ?
here I am trying to get an string as an input from user character by character. In the following code i have got input from user and stored in string[] array then in order to do some other operations i have stored the same in other array called temp_string[i]. But surprisingly i am getting garbage value in output.and also length calculated using strlen is not correct. can anybody look at this code and explain whats going wrong?
#include<stdio.h>
#include<stdio.h>
int main()
{
char ch;
int i = 0, j = 0;
int length = 0;
int lengthsb = 0;
char string[100];
printf(" Enter the string to divide\n ");
while(ch != '\n')
{
ch = getchar();
string[i] = ch;
i++;
}
char temp_string[i];
printf("%s", string);
i = 0;
while(string[i] != '\n')
{
temp_string[i] = string[i];
i++;
}
length = strlen(temp_string);
printf("Entered string is %s and its length is %d\n", temp_string, length);
}
You forgot to add the null at the end of the string.
C strings are null-terminated, that means that all operations in c strings expect a null to mark the end of the string, including functions like strlen.
you can achieve that just adding:
string[i] = '\0';
After fill the string.
Another thing, what happens if the user enters a string bigger than 100? Is good to validate the input for these cases, otherwise you can get a buffer overflow.
You need to add a NULL - terminated at the end of your string. Add \0.
You need to put a '\0' char at the end of the string so strlen(), printf() and other C functions dealing with strings will work. That is how the C API knows it reached the end of the string.
Also, you don't want to set new characters at the memory space past the string array. So you better check that in your loop (and save a last array item to set the '\0').
while (ch != '\n' && i < 99)
{
ch = getchar();
string[i] = ch;
i++;
}
string[i] = '\0'; // set the string terminator past the end of the input
Remember to do the same after copying the characters to temp_string. (By the way, you can replace that loop with a call to strcpy(), that does exactly that, except it will end only when it finds a '\0'.)
You might also want to read What's the rationale for null terminated strings?
Here is your Final Code:
#include<stdio.h>
#include<stdio.h>
#include<string.h>
int main()
{
char ch;
int i = 0, j = 0;
int length = 0;
int lengthsb = 0;
char string[100];
char temp_string[100];
printf(" Enter the string to divide\n ");
while(ch != '\n')
{
ch = getchar();
string[i] = ch;
i++;
}
string[i]=NULL;
printf("%s", string);
i = 0;
while(string[i] != '\0')
{
temp_string[i] = string[i];
i++;
}
temp_string[i]=NULL;
length = strlen(temp_string);
printf("Entered string is %s and its length is %d\n", temp_string, length);
}
In the above code what exactly you are missing is NULL or '\0' termination of the string. I just added it to make it useful.

Need help removing empty character in C

This should be relatively simple.
I've got a string/character pointer that looks like this
" 1001"
Notice the space before the 1. How do I remove this space while still retaining the integer after it (not converting to characters or something)?
The simplest answer is:
char *str = " 1001";
char *p = str+1; // this is what you need
If the space is at the beginning of string.You also can do it.
char *str = " 1001";
char c[5];
sscanf(str,"%s",c);
printf("%s\n",c);
%s will ignore the first space at the beginning of the buffer.
One solution to this is found here: How to remove all occurrences of a given character from string in C?
I recommend removing the empty space character or any character by creating a new string with the characters you want.
You don't seem to be allocating memory so you don't have to worry about letting the old string die.
If it is a character pointer, I believe
char* new = &(old++);
Should do the trick
I'm guessing your reading in a String representation of an integer from stdin and want to get rid of the white space? If you can't use the other tricks above with pointers and actually need to modify the memory, use the following functions.
You can also use sprintf to get the job done.
I'm sure there is more efficient ways to trim the string. Here is just an example.
void trim(unsigned char * str)
{
trim_front(str);
trim_back(str);
}
void trim_front(unsigned char * str)
{
int i = 0;
int index = 0;
int length = strlen(str);
while(index < length && (str[index] == ' ' || str[index] == '\t' || str[index] == '\n'))
{
index++;
}
while(index < length)
{
str[i] = str[index];
i++;
index++;
}
}
void trim_back(unsigned char * str)
{
int i;
for(i = 0; str[i] != ' ' && str[i] != '\n' && str[i] != '\t' && str[i] != '\0'; i++);
str[i] = '\0';
}

Resources