As you can see, I am trying to make a program that receives getche() and then
show it and its hex and finally putting all ´getche()´es into a string but
that resulted in printing garbage chars!
Can you tell me what's the problem?
#include <conio.h>
#include <stdlib.h>
void main(void) {
char allchars[64];
int ctr = -1;
char ch = 'a';
while (ch != '\r') {
printf("\nType a character:");
ch=getche();
printf("\nhex=%x\nch=%c",ch,ch);
ctr++;
allchars[ctr] += ch;
}
char terminate = 'a';
printf("\nAll what you typed: %s",allchars);
printf("\nPress any key to continue:");
terminate=getche();
if(getche()=='\n'){
exit(0);
}
}
output:
Type a character:t
hex=74
ch=t
Type a character:e
hex=65
ch=e
Type a character:s
hex=73
ch=s
Type a character:t
hex=74
ch=t
Type a character:
hex=d
ch=
All what you typed: ä{│t
Press any key to continue:
Process returned 13 (0xD) execution time : 21.835 s
Press any key to continue.
First of all 'allchars' is not null terminated (add a '\0' at the end of the char array).
What do you think this expression does?
allchars[ctr] += ch;
Since you do not initialize 'allchars' with any value beforehand, the value at the index 'ctr' is unknown (could be anything), but you add the character 'ch' to it (add equal).
As a result, you will have garbage at that index, at least not that what you expect it to be.
At last: what if you type more than 64 characters?
There are a couple of errors in your code, and a few other issues.
First, your line allchars[ctr] += ch; is adding the value of ch to the uninitialized existing value of the element of that array; you should use the simple assignment operator, instead: allchars[ctr] = ch;.
Second, all character strings in C that are to be used by functions like printf (with the %s format specifier) must be terminated with the NUL character (a zero value); so you need to add that after your while loop.
Another probable error (depends on your compiler/platform) is that you have not included the <stdio.h> header file - so there is no formal declaration of the printf function.
And, finally (I think), you really should be declaring your main function as returning an int (not void - although that is allowed, and was more common in days past).
Here is a version of your code with the above changes made (and commented):
#include <conio.h>
#include <stdlib.h>
#include <stdio.h> // MUST include this for the "printf" function
int main(void) // Should really use "int" return type
{
char allchars[64];
int ctr = -1;
char ch = 'a';
while (ch != '\r') {
printf("\nType a character:");
ch = getche();
printf("\nhex=%x\nch=%c", ch, ch);
ctr++;
allchars[ctr] = ch; // Just assign! (Don't add to unitialized existing value.)
}
allchars[ctr + 1] = '\0'; // We MUST add a NUL-terminator to use the "%s" format
char terminate = 'a';
printf("\nAll what you typed: %s", allchars);
printf("\nPress any key to continue:");
terminate = getche();
if (getche() == '\n') {
exit(0);
}
return 0;
}
Feel free to ask for any further clarification and/or explanation.
Related
In my code, I used a tolower function in order to eliminate letters not considering their cases. ( case insensitive) but my problem is that if my first input is "HELLO" and my 2nd is "hi" the ouput would be "ello" in lowercase letters instead of "ELLO". Is there any way to fix this? Should I not use tolower function?
#include <stdio.h>
#include <conio.h>
void main()
{
char s1[20],s2[20];
int i,j;
printf("\nEnter string 1:- ");
gets(s1);
printf("\nEnter the string for matching:- ");
gets(s2);
for(int i = 0; s1[i]; i++)
{
s1[i] = tolower(s1[i]);
}
for(int i = 0; s2[i]; i++)
{
s2[i] = tolower(s2[i]);
}
for (i=0;(i<20&&s1[i]!='\0');i++)
{
for (j=0;(j<20&&s2[j]!='\0');j++)
{
if (s1[i]==s2[j])
s1[i]=' ';
}
}
printf("\nString 1 after deletion process is %s",s1);
printf("\nIts compressed form is ");
for (i=0;(i<20&&s1[i]!='\0');i++)
{
if (s1[i]!=' ')
printf("%c",s1[i]);
}
getch();
}
Write a function
Compare the results of tolower() directly — don’t change the strings themselves
Do not use gets() and scanf("%s") — both have no bounds checking
EDIT: sorry, this function simply compares two strings. It is meant to give you an idea of how to use tolower() effectively, not do your work for you. :-)
#include <iso646.h>
#include <ctype.h>
bool is_equal( const char * a, const char * b )
{
while (*a and *b)
{
if (tolower( *a ) != tolower( *b ))
return false;
++a;
++b;
}
if (*a or *b) return false;
return true;
}
Now you can call the function directly.
if (is_equal( "HELLO", "hello" )) ...
Getting a string input from the user in C is always a pain, but you can use fgets() for that.
char s[100]; // the target string (array)
fgets( s, 100, stdin ); // get max 99 characters with null terminator
char * p = strchr( s, '\n' ); // find the Enter key press
if (p) *p = '\0'; // and remove it
puts( s ); // print the string obtained from user
You can always wrap all the annoying stuff for getting strings into a function.
Is there any way to fix this? Should I not use tolower function?
Instead of changing s1[] to lower case, leave s1[] "as is" and change the compare. Still good to change s2[].
// if (s1[i]==s2[j]) s1[i]=' ';
if (tolower(((unsigned char*)s1)[i]) == s2[j]) s1[i]=' ';
tolower(int ch) is well defined for all int values in the unsigned char range and EOF. Since a char may be negative and string processing is best done as unsigned char, use the cast. Also in the s2[] processing.
Also do not use gets(). Research fgets().
Your code has security vulnerabilities because you're using gets() (if the text input by the user is larger than 19 bytes, you'll have buffer overflows on variables s1 and s2). This function is bugged, it's not fixable and should never be used. Instead use, for example, fgets(s1, sizeof(s1), stdin).
The main idea of the problem is that you must preserve the strings, so remove the loops that modify them. In this case the correct predicate for checking if each compared character is the same without regard to case would become:
if (tolower((unsigned char)s1[i]) == tolower((unsigned char)s2[j]))
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;
}
I am a beginner coder and writing a code that
asks for the user's name
check if the length is >15, if it is, it will ask the user to input a shorter name when they restart the program
if the length is valid, upper case the first letter of the entered name
display something like "Hi name"
However, The program keeps exiting no matter what I enter. Here is what I did :
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <conio.h>
int main(void)
{
char str_name[15];
printf("Please enter your first name to begin: ");
scanf_s("%14s", str_name, _countof(str_name));
getchar();
if (strlen(str_name) > 15)
{
printf("The entered name is too long, please restart the program and try again.");
getchar();
exit(0);
}
else
{
str_name[0] = toupper(str_name[0]);
printf("Hi %s.\n", str_name);
getchar();
}
return 0;
}
You can simply use fgets() to read an input buffer.
char *fgets(char *str, int n, FILE *stream) reads a line from the specified stream and stores it in a buffer pointed to by str. It stops when either n-1 characters are read, the newline character is read, or the EOF is reached.
Some things to note about fgets():
Returns NULL on error.
Appends \n character at the end of buffer. Can replaced with \0 instead.
Buffer must be pointer to an array of characters. Either allocated on the stack or the heap.
Reads from stdin or FILE objects.
Here is some example code which shows this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define NAMESTRLEN 16
int main(void) {
char str_name[NAMESTRLEN] = {'\0'};
size_t slen;
printf("Please enter your first name to begin: ");
if (fgets(str_name, NAMESTRLEN, stdin) == NULL) {
fprintf( stderr, "Error from fgets()\n");
return 1;
}
slen = strlen(str_name);
if (slen > 0 && str_name[slen-1] == '\n') {
str_name[slen-1] = '\0';
} else {
fprintf( stderr, "Too many characters\n");
return 1;
}
if (str_name[0] == '\0') {
fprintf( stderr, "No name entered\n");
return 1;
}
str_name[0] = toupper((unsigned char)str_name[0]);
printf("Hi %s.\n", str_name);
return 0;
}
There are several issues in your code:
The buffer size is too short: scanf() will not read more than 14 bytes into str_name, so it is not possible to test if the user entered a name longer than 15 characters.
toupper() should not be given a char argument because it is only defined for values of type unsigned char and the special value EOF. Cast the char as unsigned char.
your attempt at pausing before the terminal window closes fails on windows for long names because the extra characters entered by the user are still pending after the scanf_s(). getchar() reads one and returns immediately, and the program exits and the terminal window closes. Open the terminal window and run the program manually so it does not close automatically. With this approach, you can remove the getchar() and make the program more portable.
Here is a corrected version:
#include <ctype.h>
#include <stdio.h>
int main(void) {
char str_name[17];
printf("Please enter your first name to begin: ");
if (scanf_s("%16s", str_name, sizeof(str_name))) {
printf("Premature end of file.\n");
return 1;
}
if (strlen(str_name) > 15) {
printf("The entered name is too long, please restart the program and try again.");
return 1;
}
str_name[0] = toupper((unsigned char)str_name[0]);
printf("Hi %s\n", str_name);
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
int main(void)
{
char str_name[16] = {0};
size_t len = 0;
int ch;
printf("Please enter your first name to begin: ");
while ((EOF != (ch = fgetc(stdin))) && (ch != '\n') && (len<sizeof(str_name)))
{
if (isalpha(ch))
{
str_name[len++] = ch;
}
}
if (len==sizeof(str_name))
{
fprintf(stderr, "Name too long\n");
}
else
{
str_name[len] = '\0';
printf ("Hi %c%s.\n", toupper(str_name[0]), &str_name[1]);
}
return 0;
}
As you can see I changed the input grabbing function. To check the input str len you should read byte per byte, not a whole string: fgetc do it. Using scanf with a format specifier like %14s it will return you always a trimmed string and you are not able to warn user about a too long Name.
Another point is to check that inserted chars are letters and not other kind of chars: isalpha do the job.
Moreover a c-string is composed by chars plus a null terminator ('\0', 0x00 ), so: a 15 chars string wants a 16 bytes array.
Lastly the code you wrote to mahe the first letter uppercase is completely wrong: you are passing to print a 1 char array and not a c string. My solution is one of many.
The problem is:
char Name[1]; // Declare a single element array.
Name[0] = toupper(str_name[0]); // Set it to the upper-case first letter.
// Try and print the nul-terminated string in Name - but there is no
// trailing zero (and the rest of the name is missing).
printf("Hi %s.\n", Name);
What you need is:
str_name[0] = toupper(str_name[0]);
printf("Hi %s.\n", str_name);
There is another problem that str_name[0] is a char value, and char may be signed. If you are using Windows-1252 for example, then Ä is 196, or as a signed char, -60. toupper takes an int, which must be positive¹. When -60 as a signed char is converted to int, you will get -60, and an out of range error. You need to write this as:
str_name[0] = toupper((unsigned char)str_name[0]);
printf("Hi %s.\n", str_name);
(Sorry.)
¹ Chrqlie points out the requirement is actually that the argument must be one of the values of unsigned char (which are - by definition - non-negative) or EOF (which is negative)"
I'm new to C, I have been asked to make a program in C asking to print each letter after a '.' after a user has entered an input.
For example if the user enters a..bcd..e.f..gh the output should be befg
which is the exact example I have been given in class.
I assume this would need to use pointers but I am unsure how to deal with this question, here is what I have tried to do so far. I know it is not correct, please help me understand how to use pointers to deal with this question.
#include <stdio.h>
int main() {
char *c, count =0;
printf("enter some characters");
scanf("%s", &c);
while( c != EOF ) {
if (c != '.') {
count ++;
}
else; {
printf("%s", c);
}
}
}
The program can look the following way
#include <stdio.h>
#define N 100
int main( void )
{
char s[N];
const char DOT = '.';
printf( "Enter some characters: " );
fgets( s, N, stdin );
for ( char *p = s; *p; ++p )
{
if ( p[0] == DOT && p[1] != DOT ) putchar( p[1] );
}
putchar( '\n' );
}
Its output might look like
Enter some characters: a..bcd..e.f..gh
befg
Take into account that here any symbol after a dot (except the dot itself) is printed. You can add a check that there is a letter after a dot.
You don't really need pointers for this, or even an array. Basically it's a simple state engine: read each character, if '.' is encountered, set a flag so the next character is printed.
#include <stdio.h>
int main() {
int c, flag = 0;
while ((c = getchar()) != EOF) {
if (c == '.')
flag = 1;
else if (flag) {
putchar(c);
flag = 0;
}
}
return 0;
}
There are some errors in your code:
- char* c means a pointer to one or more characters.
But where does it point to?
- scanf reads a string up to an "white space". White space characters are the space itself, a newline, a tab character or an EOF. scanf expects a format string and a pointer to a place in memory where it places what it reads. In your case c points to an undefined place and will overwrite whatever there is in memory.
- why do you place a ";" after the else? The else clause will end with the ";". So your program will do the print every time.
It helps you a lot if you format your code in a more readable way and give the variable names that give hint what they are used for.
Another very important thing is to initialize every variable that you declare. Errors with uninitialized variables are sometimes very hard to find.
I would do it this way:
#include <stdio.h>
int main(int argc, char* argv[])
{
// I read every single character. The getchar function returns an int!
int c = 0;
// This marks the program state whether we must print the next character or not
bool printNext = false;
printf("enter some characters");
// We read characters until the buffer is empty (EOF is an integer -1)
do
{
// Read a single character
c = getchar();
if ( c == '.')
{
// After a point we change our state flag, so we know we have to print the next character
printNext = true;
}
else if( c != EOF )
{
// When the character is neither a point nor the EOF we check the state
if( printNext )
{
// print the character
printf( "%c", c );
// reset the state flag
printNext = false;
}
}
// read until the EOF occurs.
}
while( c != EOF );
}
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int main()
{
char letter;
char *c;
c = malloc(256);
printf("enter the string : ");
scanf("%s", c);
while( (letter=*(c)) != '\0' )
{
if (letter == '.')
{
c++;
letter=*c;
if(letter!='.')
printf("%c",letter);
else
{
while(letter=='.')
{
c++;
letter=*c;
}
printf("%c",letter);
}
}
c++;
}
printf("\n");
}
I'm trying to write a code that asks the user to enter a string and takes of all characters except the alphabetical.
Now i did it myself and it doesn't seem to work properly. I'm new to strings so i'm trying to understand and master strings. I tried to use gdb on mac but i don't have all the functions to understand this.
Could you please help?
What the code must do: User inputs (for example): h**#el(l)o&^w
and the output is hello.
here is my code:
#include <stdio.h>
#include <string.h>
int main()
{
char string[100];
int i;
int seen = 0;
printf("Enter String: ");
scanf("%s", string);
for (i=0; string[i]!='\0'; i++)
{
if (((string[i]<='a' || string[i]>'z')&&(string[i]<='A' || string[i]>'Z')) ||string[i]!='\0')
{
seen = 1;
}
else
seen = 0;
}
if (seen==0)
{
printf("%s", string);
}
}
well, your code has a couple of important problems:
you're not checking boundaries when iterating… what if I type in a 101 characters string? and a 4242 characters string?
next problem, is that scanf("%s", …) is considered dangerous, for the same reasons
so basically, what you'd want is to use fgets() instead of scanf().
But why not just get the input character by character, and build a string that has only the chars you want? It's simpler and flexible!
basically:
#include <ctype.h>
int main() {
char* string[100];
int i=0;
printf("Enter your string: ");
do {
// getting a character
char c = getchar();
// if the character is alpha
if (isalpha(c) != 0)
// we place the character to the current position and then increment the index
string[i++] = c;
// otherwise if c is a carriage return
else if (c == '\r') {
c = getchar(); // get rid of \n
// we end the string
string[i] = '\0'
}else if (c == '\n')
// we end the string
string[i] = '\0';
// while c is not a carriage return or i is not out of boundaries
} while (c != '\n' || i < 100);
// if we've got to the boundary, replace last character with end of string
if (i == 100)
string[i] = '\0';
// print out!
printf("Here's your stripped string: %s\n", string);
return 0;
}
I did not run it on my computer because it's getting late, so my apologies in case of mistakes.
Addendum:
wee the program skips my statement and shuts down
that's because your condition is inversed, and remove the \0 condition, as it will always happen with the scanf() that always append \0 to the string to end it. Try exchanging seen = 1 and seen = 0 or try using the following condition:
if ((string[i]>='a' && string[i]<='z')||(string[i]>='A' && string[i]<='Z')))
seen = 1;
else
seen = 0;
or simply, use ctypes's isalpha() function, like in our two examples!
No part(remove the extra characters) to change the string in your code.
#include <stdio.h>
#include <string.h>
#include <ctype.h>
char *filter(char *string, int (*test)(int)) {
char *from, *to;
for(to = from = string;*from;++from){
if(test(*from))
*to++ = *from;
}
*to = '\0';
return string;
}
int main(){
char string[100];
printf("Enter String: ");
scanf("%99s", string);
printf("%s\n", filter(string, isalpha));
return 0;
}