Like if your file has the following text: CompuTEr. Then after running your code the content of the file should be: cOMPUteR!
But problem is only one character which is a. It is not changing into Captial A.
#include<stdio.h>
#include<conio.h>
#include <ctype.h>
int main()
{
char name[100];
int loop;
printf("Enter any Sting: ");
gets(name);
for (loop=0; name[loop] !=0; loop++)
{
if(name[loop]>='A' && name[loop]<='Z')
name[loop]=name[loop]+32;
else if(name[loop]>'a' && name[loop]<='z')
name[loop]=name[loop]-32;
}
printf("\nConvert case of character : %s",name);
return 0;
}
Change
else if(name[loop]>'a' && name [loop]<='z')
To
else if(name[loop]>='a' && name [loop]<='z')
And Never ever use gets(). It is dangerous because it dosen't prevent buffer overflows. Use fgets() instead:
fgets(name,sizeof(name),stdin);
There are many problems with your code:
#include<stdio.h>
Use proper spacing: #include <stdio.h>.
While most spacing is not required, consistent use of spaces and indentation greatly enhances code readability and reduces the number of bugs. If you use sloppy style, you probably also use buggy algorithms and careless constructs. Bugs will have more places to hide. C is a very sharp tool, it is unforgiving with the careless.
#include<conio.h>
This header is an obsolete, Microsoft specific thing. It is not required here.
#include <ctype.h>
ctype.h defines the right functions for your assignment, but you don't even use them!
int main()
Define main as int main(void) or int main(int argc, char *argv[])
{
char name[100];
int loop;
printf("Enter any Sting: ");
So this whole thing was just a sting? Interesting lapsus!
gets(name);
Definitely never ever use gets! If the user types more than 99 characters at the prompt, gets will cause a buffer overflow as it cannot determine the size of name. This buffer overflow will most likely cause the program to crash, but careful exploitation of such a flaw can allow an attacker to take control of the computer. This is a very good and simple example of a security flaw. scanf is more complicated, inefficient and difficult to use safely in this context, as in most. Just use fgets and handle the trailing '\n' appropriately.
for (loop=0; name[loop] !=0; loop++)
The common idiom for this loop is to use an index variable called i. Naming it loop is confusing and verbose. The comparison to 0 could be written more simply as name[loop] is your teacher condones it, or name[loop] == '\0' to make it clear that you are comparing characters.
{
if(name[loop]>='A' && name[loop]<='Z')
You should use isupper to test for upper-case. Comparing explicitly to character values 'A' and 'Z' is non portable and error prone as you don't seem to get your comparisons right.
name[loop]=name[loop]+32;
You are assuming ASCII or similar encoding. This dirty trick is non portable, confusing and error prone. Just use the tolower function.
else if(name[loop]>'a' && name[loop]<='z')
Same remark as above. Your code is buggy. Proper use of spacing and less verbose index name should make the bug more obvious:
else if (name[i] > 'a' && name[i] <= 'z')
Use islower for both portability and reliability.
name[loop]=name[loop]-32;
See above. toupper was designed for this purpose.
}
printf("\nConvert case of character : %s",name);
Fix the broken English. Also add a '\n' at the end of the format string. Some systems will not even output anything if you don't.
return 0;
}
Proofing your homework online is only useful if you learn from it. I hope you did!
Related
For some homework I have to write a calculator in C. I wanted to input some string with scanf and then access it. But when I access the first element I get a segmentation error.
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
int main(){
char input1[30];
scanf("%s",input1);
printf("%s",input1);
char current = input1[0];
int counter = 0;
while(current != '\0'){
if(isdigit(current) || current == '+' || current == '-' || current == '*' || current == '/'){
counter++;
current = input1[counter];
}else{
printf("invalid input\n");
exit(1);
}
}
return 0;
}
The printf in line 3 returns the string, but accessing it in line 4 returns a segmentation error (tested in gdb). Why?
There are a few potential causes, some of which have been mentioned in the comments (I won't cover those). It's hard to say which one (or more) is the cause of your problem, so I guess it makes sense to iterate them. However, you may notice that I cite some resources in the process... The information is out there, yet you're not stumbling across it until it's too late. Something needs to change with how you research, because this is slowing your progress down.
On input/output dynamics, just a quick note
printf("%s",input1);
Unless we include a trailing newline, this output may be delayed (or "buffered"), which may have the effect of confusing you about the root of your issues. As an alternative to using a trailing newline (which I'd prefer, personally) you could explicitly force partial lines to be written by invoking fflush(stdout) immediately after each of the relevant output operations, or use setbuf to disable buffering entirely. I think this is unlikely to be your problem, but it may mask your problem, so it's important to realise, when using printf to debug, it might be best to include a trailing newline...
On main entry points
The first potential culprit I see is here:
int main()
I don't know why our education system is still pushing these broken lessons. My only guess is the professors learnt many years back using the nowadays irrelevant Turbo C and don't want to stay up-to-date with tech. We can further reduce this to a simple testcase to work out if this is your segfault, but like I said, it's hard to say whether this is actually your problem...
int main() {
char input1[30];
memset(input1, '\x90', sizeof input1);
return 0; // this is redundant for `main` nowadays, btw
}
To explain what's going on here, I'll cite this page, which you probably ought to go and read (in its entirety) once you're done here:
A common misconception for C programmers, is to assume that a function prototyped as follows takes no arguments:
int foo();
In fact, this function is deemed to take an unknown number of arguments. Using the keyword void within the brackets is the correct way to tell the compiler that the function takes NO arguments.
Simply put, if the linker doesn't know/can't work out how many arguments are required for the entry point, there's probably gonna be some oddness to your callstack, and that's gonna occur at the beginning or end of your program.
On input errors, return values and uninitialised access
#include <assert.h>
#include <stdio.h>
#include <string.h>
int main(void) {
char input1[30];
memset(input1, '\x90', sizeof input1);
scanf("%s",input1); // this is sus a.f.
assert(memchr(input1, '\0', sizeof input1));
}
In my testcase, I actually wrote '\x90' to each byte in the array, to show that if the scanf call fails you may end up with an array that has no null terminator. If this is your problem, this assertion is likely to throw (as you can see from the ideone demo) when you run it, which indicates that your loop is likely accessing garbage beyond the bounds of input1. On this note I intended to demonstrate that we (mostly) cannot rely upon scanf and friends unless we also check their return values! There's a good chance your compiler is warning you about this one, so another lesson is uto pay close attention to warning messages, and strive to have none.
On argument expectations for standard library functions
For many standard library functions it may be possible to give input that is outside of the acceptable domain, and so causes instability. The most common form, which I also see in your program, exists in the form of possibly passing invalid values to <ctype.h> functions. In your case, you could change the declaration of current to be an unsigned char instead, but the usual idiom is to put the cast explicitly in the call (like isdigit((unsigned char) current)) so the rest of us can see you're not stuck in this common error, at least while you're learning C.
Please note at this point I'm thinking whichever resources you're using to learn aren't working, because you're stumbling into common traps... please try to find more reputable resources to learn from so you don't fall into more common traps and waste more time later on. If you're struggling, check out the C tag wiki...
int main()
{
char ch = 0;
int c = 0;
scanf("%d", &ch);
printf("%c", ch);
}
I can input the ASCII number and output the correct character. But the program crashes at the end of the code, the } sign.
Using Visual Studio 2019
Run-Time Check Failure #2 - Stack around the variable 'ch' was corrupted.
Since scanf has non-existent type safety, it can't know the type of parameters passed (one reason why the format string is there in the first place).
The stack corruption is caused by you lying to the compiler here: scanf("%d", &ch);. You tell it "trust me, ch is an int". But it isn't. So scanf tries to store 4 bytes in an area where only 1 byte is allocated and you get a crash.
Decent compilers can warn for incorrect format specifiers.
There are multiple problems in your code:
missing #include <stdio.h> ;
unused variable c ;
type mismatch passing a char variable address when scanf() expects an int * for the %d conversion specifier ;
missing test on scanf() return value ;
missing newline at the end of the output ;
missing return 0; (implied as of c99, but sloppy).
Here is a modified version:
#include <stdio.h>
int main() {
int ch;
if (scanf("%d", &ch) == 1) {
printf("%c\n", ch);
}
return 0;
}
I guess your question was not, "What did I do wrong?", or "Why didn't it work?".
I guess your question is, "Why did it work?", or, "Why did it print an error message after seeming to work correctly?"
There are lots of mistakes you can make which will corrupt the stack. This is one of them. Much of the time, these errors are rather inscrutable: If the memory corruption is severe enough that the memory management hardware can detect it, you may get a generic message like "Segmentation violation" at the instant the bad access occurs, but if not, if the damage isn't bad enough to cause any overt problems, your program may seem to work as you expected, despite the error.
It would be prohibitively expensive to perform explicit tests (in software) to check the stack for damage during every operation. Therefore, no attempt is made to do so, and the primary responsibility is placed on you, the programmer, not to do obviously wrong things like telling scanf to store an int in a char-sized box.
In this case, your system did make a check for stack damage, but as some kind of a one-time operation, only after the main function had returned. That's why the scanf and the printf seemed to work correctly, and the error message seemed to coincide with the closing } at the end of main.
Echoing an analogy I made in a comment, this is sort of like having a policeman write you a ticket for having done something dangerous that did not cause an accident. Why not write the ticket as you are doing the dangerous thing? Why write the ticket after the fact at all, since your dangerous behavior didn't cause an accident? Well, because sometimes that's just the way the world works.
I think you are trying to input an integer and print its char value so in my opinion this is what you are trying to do:
#include <iostream>
using namespace std;
int main()
{
int c = 0;
scanf("%d", &c);
printf("%c", c);
return 0;
}
Note: This is a C++ code but the syntax inside main function will work for C language as well
Is there any way to handle error index out of bounds in C
i just want to to know, please explain it in context of this example.
if i enter a string more than 20 char i get * stack smashing detected *: ./upper1 terminated
Aborted (core dumped)
main()
{
char st[20];
int i;
/* accept a string */
printf("Enter a string : ");
gets(st);
/* display it in upper case */
for ( i = 0 ; st[i] != '\0'; i++)
if ( st[i] >= 'a' && st[i] <= 'z' )
putchar( st[i] - 32);
else
putchar( st[i]);
}
I want to handle those and stop them and display a custom message as done in Java's Exception Handling. Is it possible ? If yes how
Thanks in advance
To answer the original question: there is no way to handle implicitly out-of-bound array indexes in C. You should add that check explicitly in your code or you should prove (or at least be absolutely sure) that it does not happen. Beware of buffer overflow and other undefined behavior, it can hurt a lot.
Remember that C arrays don't "know" their size at runtime. You should know and manage that size, especially when passing arrays (which become decayed into pointers). Read also about flexible array members in struct-s (like here).
BTW, your code is poor taste. First, the char st[20]; is really too small these days: an input line can have really a hundred of characters (I often have terminal emulators wider than 80 columns). So make it e.g.
char st[128];
Then, as every one told you, gets(3) is dangerous, it is documented as "Never use this function". Take the habit of reading the documentation of every function that you dare use.
I would suggest to always clear such a string buffer with
memset (st, 0, sizeof st);
You should at the very least use fgets(3), but read the documentation first. You'll need to handle the failure case.
Also, your conversion to upper-case is specific to ASCII (and some other encodings). It won't work on old EBCDIC machine. And it is unreadable. So use isalpha(3) to detect letters (in ASCII or other single-byte encoding); but in UTF-8 it is more complex, since some letters -eg cyrillic ones- are encoded on several bytes). My family name (СТАРЫНКЕВИЧ when spelt in Russian) contains an Ы -which is a single letter called yery - whose UTF-8 encoding for the capital letter is 0xD0 0xAB on two bytes. You'll need an UTF-8 library like unistring to handle these. And use toupper(3) to convert (e.g. ASCII) letters to upper-case.
Notice that your main function is wrongly defined. It should return an int and preferably be declared as int main(int argc, char**argv).
At last, on Posix systems, the "right" way to read a line is to use the getline(3) function. It can read a line as wide as permitted by system resources (so it might read a line of a million characters on my machine). See this answer.
Regarding exceptions, C don't really have these (so most programmers take the habit to have functions giving some error code). However, for non-local jumps consider setjmp(3) to be used with great caution. (In C++, you have exceptions and they are related to destructors).
Don't forget to compile with all warnings and debug info (e.g. with gcc -Wall -g if using GCC). You absolutely need to learn how to use the debugger (e.g. gdb) and you also should use a memory leak detector like valgrind.
Yes, you must use fgets() instead of gets(). In fact, gets() is officially deprecated and should never, ever be used, because it is impossible to use safely as you discovered.
Though its not directly possible to detect that the user has written out of bounds it, we can add some logic to make sure to throw an error without crashing.
int main (int argc, char **argv)
{
char user_input [USERINPUT_MAX];
for (int i = 0; i < USERINPUT_MAX; ++i)
{
// read the character
// check for enter key, if enter break out of loop after adding null at end
// if not enter,store it in array
}
if (i == USERINPUT_MAX)
{
printf ("you have exceeded the character range");
}
}
I guess you get the idea of how to handle such situations from user input.
I am trying to create a lexical analyzer in C.
The program reads another program as input to convert it into tokens, and the source code is here-
#include <stdio.h>
#include <conio.h>
#include <string.h>
int main() {
FILE *fp;
char read[50];
char seprators [] = "\n";
char *p;
fp=fopen("C:\\Sum.c", "r");
clrscr();
while ( fgets(read, sizeof(read)-1, fp) !=NULL ) {
//Get the first token
p=strtok(read, seprators);
//Get and print other tokens
while (p!=NULL) {
printf("%s\n", p);
p=strtok(NULL, seprators);
}
}
return 0;
}
And the contents of Sum.c are-
#include <stdio.h>
int main() {
int x;
int y;
int sum;
printf("Enter two numbers\n");
scanf("%d%d", &x, &y);
sum=x+y;
printf("The sum of these numbers is %d", sum);
return 0;
}
I am not getting the correct output and only see a blank screen in place of output.
Can anybody please tell me where am I going wrong??
Thank you so much in advance..
You've asked a few question since this one, so I guess you've moved on. There are a few things that can be noted about your problem and your start at a solution that can help others starting to solve a similar problem. You'll also find that people can often be slow at answering things that are obvious homework. We often wait until homework deadlines have passed. :-)
First, I noted you used a few features specific to Borland C compiler which are non-standard and would not make the solution portable or generic. YOu could solve the problem without them just fine, and that is usually a good choice. For example, you used #include <conio.h> just to clear the screen with a clrscr(); which is probably unnecessary and not relevant to the lexer problem.
I tested the program, and as written it works! It transcribes all the lines of the file Sum.c to stdout. If you only saw a blank screen it is because it could not find the file. Either you did not write it to your C:\ directory or had a different name. As already mentioned by #WhozCraig you need to check that the file was found and opened properly.
I see you are using the C function strtok to divide the input up into tokens. There are some nice examples of using this in the documentation you could include in your code, which do more than your simple case. As mentioned by #Grijesh Chauhan there are more separators to consider than \n, or end-of-line. What about spaces and tabs, for example.
However, in programs, things are not always separated by spaces and lines. Take this example:
result=(number*scale)+total;
If we only used white space as a separator, then it would not identify the words used and only pick up the whole expression, which is obviously not tokenization. We could add these things to the separator list:
char seprators [] = "\n=(*)+;";
Then your code would pick out those words too. There is still a flaw in that strategy, because in programming languages, those symbols are also tokens that need to be identified. The problem with programming language tokenization is there are no clear separators between tokens.
There is a lot of theory behind this, but basically we have to write down the patterns that form the basis of the tokens we want to recognise and not look at the gaps between them, because as has been shown, there aren't any! These patterns are normally written as regular expressions. Computer Science theory tells us that we can use finite state automata to match these regular expressions. Writing a lexer involves a particular style of coding, which has this style:
while ( NOT <<EOF>> ) {
switch ( next_symbol() ) {
case state_symbol[1]:
....
break;
case state_symbol[2]:
....
break;
default:
error(diagnostic);
}
}
So, now, perhaps the value of the academic assignment becomes clearer.
I am originally a Java programmer who is now struggling with C and specifically C's pointers.
The idea on my mind is to receive a string, from the user, on a command line, into a character pointer. I then want to access its individual elements. The idea is later to devise a function that will reverse the elements' order. (I want to work with anagrams in texts.)
My code is
#include <stdio.h>
char *string;
int main(void)
{
printf("Enter a string: ");
scanf("%s\n",string);
putchar(*string);
int i;
for (i=0; i<3;i++)
{
string--;
}
putchar(*string);
}
(Sorry, Code marking doesn't work).
What I am trying to do is to have a first shot at accessing individual elements. If the string is "Santillana" and the pointer is set at the very beginning (after scanf()), the content *string ought to be an S. If unbeknownst to me the pointer should happen to be set at the '\0' after scanf(), backing up a few steps (string-- repeated) ought to produce something in the way of a character with *string. Both these putchar()'s, though, produce a Segmentation fault.
I am doing something fundamentally wrong and something fundamental has escaped me. I would be eternally grateful for any advice about my shortcomings, most of all of any tips of books/resources where these particular problems are illuminated. Two thick C books and the reference manual have proved useless as far as this.
You haven't allocated space for the string. You'll need something like:
char string[1024];
You also should not be decrementing the variable string. If it is an array, you can't do that.
You could simply do:
putchar(string[i]);
Or you can use a pointer (to the proposed array):
char *str = string;
for (i = 0; i < 3; i++)
str++;
putchar(*str);
But you could shorten that loop to:
str += 3;
or simply write:
putchar(*(str+3));
Etc.
You should check that scanf() is successful. You should limit the size of the input string to avoid buffer (stack) overflows:
if (scanf("%1023s", string) != 1)
...something went wrong — probably EOF without any data...
Note that %s skips leading white space, and then reads characters up to the next white space (a simple definition of 'word'). Adding the newline to the format string makes little difference. You could consider "%1023[^\n]\n" instead; that looks for up to 1023 non-newlines followed by a newline.
You should start off avoiding global variables. Sometimes, they're necessary, but not in this example.
On a side note, using scanf(3) is bad practice. You may want to look into fgets(3) or similar functions that avoid common pitfalls that are associated with scanf(3).