What does this line of code do? [Newbie] - c

int main(void)
{
string n = GetString();
if(n!=NULL){
for(int i=0, j=strlen(n); i<j; i++){
if(!isalpha(n[i-1]) && isalpha(n[i])){
printf("%c", toupper(n[i]));
}
}
}
}
if(!isalpha(name[i-1]) && isalpha(name[i]))
how can this line be explained to a new starter?(by the way the code works properly on harvard's cs50 ide)

The code is attempting to find every occurrence of a non-alphabetic character in the array n followed by an alphabetic character and, in each one, print that alphabetic character in upper case.
The problem is, since i starts with the value of 0, the code has undefined behaviour in the first iteration since it accesses a character before the start of the array.
The code might seem to work properly under cs50, but that is just happenstance. One feature of undefined behaviour is that it is not required to produce any error, or any unexpected results. But that doesn't make it right. It simply means that it did not produce an observable symptom in some set of circumstances.
Note: for sake of discussion, I am assuming string is a pointer to char, and that GetString() returns the address of the first character in an array of char.

Related

Integer to pointer type conversion

int count_words(string word)
{
string spaces = "";
int total_words = 1;
int i, j = 0 ;
for (i = 0; i < strlen(word); i++)
{
strcpy(spaces, word[i]);
if (strcmp(spaces, " ") == 0)
{
total_words = total_words + 1;
}
}
return total_words;
}
I am trying to make a function in c that gets the total number of words, and my strategy is to find the number of spaces in the string input. However i get an error at strcpy about integer to ptrtype conversion,. I cant seem to compare the 2 strings without getting the error. Can someone explain to me whats how the error is happening and how I would go about fixing it. The IDE is also suggesting me to add an ampersand beside word[i] but it then makes a segmentation fault output
You need to learn a little more about the distinction between characters and strings in C.
When you say
strcpy(spaces, word[i]);
it looks like you're trying to copy one character to a string, so that in the next line you can do
if (strcmp(spaces, " ") == 0)
to compare the string against a string consisting of one space character.
Now, it's true, if you're trying to compare two strings, you do have to call strcmp. Something like
if (spaces == " ") /* WRONG */
definitely won't cut it.
In this case, though, you don't need to compare strings. You're inspecting your input a character at a time, so you can get away with a simple character comparison instead. Get rid of the spaces string and the call to strcpy, and just do
if (word[i] == ' ')
Notice that I'm comparing against the character ' ', not the string " ". Using == to compare single characters like this is perfectly fine.
Sometimes, you do have to construct a string out of individual characters, "by hand", but when you do, it's a little more elaborate. It would look like this:
char spaces[2];
spaces[0] = word[i];
spaces[1] = '\0';
if (strcmp(spaces, " ") == 0)
...
This would work, and you might want to try it to be sure, but it's overkill, and there's no reason to write it that way, except perhaps as a learning exercise.
Why didn't your code
strcpy(spaces, word[i]);
work? What did the error about "integer to pointer conversion" mean? Actually there are several things wrong here.
It's not clear what the actual type of the string spaces is (more on this later), but it has space for at most 0 characters, so you're not going to be able to copy a 1-character string into it.
It's also not clear that spaces is even writable. It might be a constant, meaning that you can't legally copy any characters into it.
Finally, strcpy copies one string to another. In C, although strings are arrays, they're usually referred to as pointers. So strcpy accepts two pointers, one to the source and one to the destination string. But you passed it word[i], which is a single character, not a string. Let's say the character was A. If you hadn't gotten the error, and if strcpy had tried to do its job, it would have treated A as a pointer, and it would have tried to copy a string from address 65 in memory (because the ASCII value of the character A is 65).
This example shows that working with strings is a little bit tricky in C. Strings are represented as arrays, but arrays are second-class citizens in C. You can't pass arrays around, but arrays are usually referred to by simple pointers to their first element, which you can pass around. This turns out to be very convenient and efficient once you understand it, but it's confusing at first, and takes some getting used to.
It might be nice if C did have a built-in, first-class string type, but it does not. Since it does not, C programmers myst always keep in mind the distinction between arrays and characters when working with strings. That "convenient" string typedef they give you in CS50 turns out to be a bad idea, because it's not actually convenient at all -- it merely hides an important distinction, and ends up making things even more confusing.

C line printed from file undefined behavior

I have made a c program that parses through the source code file of a language called rapid to extract certain data that I will need to document at work. the data extracted is saved to a csv file that is then formatted into an excel worksheet.
Everything is working except for this function that I have put below. In certain scenarios I was wanting to remove all of the spaces and tabs from a line read from a file so that I can store the statement as a string, in a struct attribute.
The program isn't crashing, but when I printf() the new line with the whitespace removed, some other characters get printed out to.
Example "cmd.exe" , "PowerShell\v1.0\Modules", "igh\AppData\LocaloYSφo¡"
If I do Printf("%s\n", currentLine); It prints fine
When I use printf("%s\n", removeWhiteSpace(currentLine)); I get the undefined behavior.
Here is the function
/******************************************************************
* Takes a string as input, returns it without tabs or spaces
* Used to put whole line into the additional commands
* Attribute
******************************************************************/
static char* removeWhiteSpace(char* string)
{
int i;
int j;
int len = strlen(string);
char ch;
char* result = malloc(sizeof(char)*len+1);
memset(result, 0, sizeof(*result));
j=0;
for (i=0; i<len; i++)
{
ch = string[i];
if ((ch != ' ') && (ch != '\t'))
{
result[j] = ch;
j++;
}
}
result[strlen(result)] = '\0';
return result;
}
Also, I am using fgets() to get the line from the file, and the size for the buffer is at 1000.
The unwanted characters don't exist in the text file, at least not visible anyways.
Thank you for your time, and if you need the text file or the rest of the program I can provide it, but it is lengthy.
Also, I'm using codeblocks IDE using the GCC compiler, I have no errors or warnings when I compile.
memset(result, 0, sizeof(*result));
That is wrong. *result is the thing result points to. result is char *, so it points to a char, and the size of a char is 1. So that statement sets one char to zero. It does not set the entire block of allocated memory to zero.
As we will see, it is unneeded, so just delete that statement.
result[strlen(result)] = '\0';
This statement is useless. strlen works by finding the first null (zero) character in an array. So strlen(result) would report where the first null character is. Then result[strlen(result)] = '\0'; would set that character to zero. But it is already zero. So this statement can never accomplish anything. More than that, though, it does not work because the memset above failed to set the memory to zero, so there may be no null character inside the allocated memory to find. In that case, the behavior is not defined by the C standard.
However, there is no need to use strlen to find the end of the string. We know where the end of the string should be. The object j has been counting the characters written to result. So just delete this line too and use:
result[j] = '\0';
When I use printf("%s\n", removeWhiteSpace(currentLine)); I get the undefined behavior.
That does not make any sense. “Undefined behavior” is not a thing. It is a lack of a thing. Saying something has “undefined behavior” means the C standard does not define what the behavior is. A program that has undefined behavior may print nothing, it may print a desired result, it may print an undesired result, it may print garbage characters, it may crash, and it may hang.
Saying a program produced undefined behavior does not tell anybody what happened. Instead, you should have written a specific description of the behavior of the program, such as “The program printed the expected text followed by unexpected characters.” A copy-and-paste of the exact input and the exact output would be good.

Removing spaces in a string

I was trying to remove spaces of a string after scanning it. The program has compiled perfectly but it is not showing any output and the output screen just keeps getting shut down after scanning the string. Is there a logical error or is there some problem with my compiler(I am using a devc++ compiler btw).
Any kind of help would be appreciated
int main()
{
char str1[100];
scanf("%s",&str1);
int len = strlen(str1);
int m;
for (m=0;m<=len;){
if (&str1[m]==" "){
m++;
}
else {
printf("%c",&str1[m]);
}
m++;
}
return 0;
}
Edit : sorry for the error of m=1, I was just checking in my compiler whether that works or not and just happened to paste that code
Your code contains a lot of issues, and the behaviour you describe is very likely not because of a bug in the compiler :-)
Some of the issues:
Use scanf("%s",str1) instead of scanf("%s",&str1). Since str1 is defined as a character array, it automatically decays to a pointer to char as required.
Note that scanf("%s",str1) will never read in any white space because "%s" is defined as skipping leading white spaces and stops reading in when detecting the first white space.
In for (m=1;m<=len;) together with str1[m], note that an array in C uses zero-based indizes, i.e. str1[0]..str1[len-1], such that m <= len exceeds array bounds. Use for (m=0;m<len;) instead.
Expression &str1[m]==" " is correct from a type perspective, but semantically a nonsense. You are comparing the memory address of the mth character with the memory address of a string literal " ". Use str1[m]==' ' instead and note the single quotes denoting a character value rather than double quotes denoting a string literal.
Statement printf("%c",&str1[m]) passes the memory address of a character to printf rather than the expected character value itself. Use printf("%c",str1[m]) instead.
Hope I found everything. Correct these things, turn on compiler warnings, and try to get ahead. In case you face further troubles, don't hesitate to ask again.
Hope it helps a bit and good luck in experiencing C language :-)
There are many issues:
You cannot read a string with spaces using scanf("%s") , use fgets instead (see comments).
scanf("%s", &str1) is wrong anyway, it should be scanf("%s", str1);, str1 being already the address of of the string
for (m = 0; m <= len;) is wrong, it should be for (m = 0; m < len;), because otherwise the last character you will check is the NUL string terminator.
if (&str1[m]==" ") is wrong, you should write if (str1[m]==' '), " " does not denote a space character but a string literal, you need ' ' instead..
printf("%c", &str1[m]); is wrong, you want to print a char so you need str1[m] (without the &).
You should remove both m++ and put that into the for statement: for (m = 1; m < len; m++), that makes the code clearer.
And possibly a few more problems.
And BTW your attempt doesn't remove the spaces from the string, it merely displays the string skipping spaces.
There are a number of smaller errors here that are adding up.
First, check the bounds on your for loop. You're iterating from index 1 to index strlen(str1), inclusive. That's a reasonable thing to try, but remember that in C, string indices start from 0 and go up to strlen(str1), inclusive. How might you adjust the loop to handle this?
Second, take a look at this line:
if (&str1[m] == " ") {
Here, you're attempting to check whether the given character is a space character. However, this doesn't do what you think it does. The left-hand side of this expression, &str1[m], is the memory address of the mth character of the string str1. That should make you pause for a second, since if you want to compare the contents of memory at a given location, you shouldn't be looking at the address of that memory location. In fact, the true meaning of this line of code is "if the address of character m in the array is equal to the address of a string literal containing the empty string, then ...," which isn't what you want.
I suspect you may have started off by writing out this line first:
if (str1[m] == " ") {
This is closer to what you want, but still not quite right. Here, the left-hand side of the expression correctly says "the mth character of str1," and its type is char. The right-hand side, however, is a string literal. In C, there's a difference between a character (a single glyph) and a string (a sequence of characters), so this comparison isn't allowed. To fix this, change the line to read
if (str1[m] == ' ') {
Here, by using single quotes rather than double quotes, the right-hand side is treated as "the space character" rather than "a string containing a space." The types now match.
There are some other details about this code that need some cleanup. For instance, look at how you're printing out each character. Is that the right way to use printf with a character? Think about the if statement we discussed above and see if you can tinker with your code. Similarly, look at how you're reading a string. And there may be even more little issues here and there, but most of them are variations on these existing themes.
But I hope this helps get you in the right direction!
For loop should start from 0 and less than length (not less or equal)
String compare is wrong. Should be char compare to ' ' , no &
Finding apace should not do anything, non space outputs. You ++m twice.
& on %c output is address not value
From memory, scanf stops on whitespace anyway so needs fgets
int main()
{
char str1[100];
scanf("%s",str1);
int len = strlen(str1);
int m;
for (m=0;m<len;++m){
if (str1[m]!=' '){
printf("%c",str1[m]);
}
}
return 0;
}
There are few mistakes in your logic.
scanf terminates a string when it encounter any space or new line.
Read more about it here. So use fgets as said by others.
& in C represents address. Since array is implemented as pointers in C, its not advised to use & while getting string from stdin. But scanf can be used like scanf("%s",str1) or scanf("%s",&str[1])
While incrementing your index put m++ inside else condition.
Array indexing in C starts from 0 not 1.
So after these changes code will becames something like
int main()
{
char str1[100];
fgets(str1, sizeof str1 , stdin);
int len = strlen(str1);
int m=0;
while(m < len){
if (str1[m] == ' '){
m++;
}
else {
printf("%c",str1[m]);
m++;
}
}
return 0;
}

Comparing char array elements

I'm trying to arrange this character array that only contains digits,it prints the same array with the order I input it without any change , i tried using type casting in the if statement, it gave me correct results when running but it wasn't accepted by the online judge.what is the fault here and why isn't my second solution accepted?
#include <stdio.h>
#include <string.h>
int main() {
char x[101];
scanf("%s",x);
int l,i,j ;
l = strlen(x);
char temp ;
for(i=0;x[i];i++)
{
for( j=i ; x[j] ; j++){
if('x[j]'<'x[i]') //(int)x[j] and (int)x[i] didn't work on the
//online judge
{
temp=x[i];
x[i]=x[j];
x[j]=temp;
}
}
}
printf("%s",x);
return 0 ;
}
I have no idea why there are quotes around the array elements, but that is not doing what you think, the comparison is happening because a multicharacter string is evaluated to an integer value which is implementation defined, hence the if statement is always comparing the same values, which means that it will always give the same result, you need to remove the quotes
if (x[j] < x[i])
Also, i'd recommend specifying the length of the array to scanf() and checking that it successfuly read the value, like this
if (scanf("%100s", x) != 1)
return -1; /* Perhaps EOF, i.e. you pressed Ctrl+D or (Ctrl+Z MS Windows) */
If you don't check your program will invoke undefined behavior, and if here it doesn't hurt any critical part of your simple program, if you don't learn to do it, then you will have a lot of hard do debug bugs in the future when you write a bigger program.
The quotes in your if statement evaluate to multicharacter constants, which in my compiler (VC++ 2013) happen to be 785B6A5D and 785B695D respectively, which are the ASCII codes of these characters glued together. Thus that if never executes. Also, what do you mean by "didn't work"? Did you get a compilation error? If yes, what did it say? Otherwise you may have exceeded the time limit since bubble sort is extremely slow.

Reading a string is not going properly

Hey guys, i'm working on a program that gets a postfix expression and calculates it..
I have two functions:
Converts infix to postfix
Calculate the postfix
When I try small expressions, like 1+1 or (1+1)*1, it works fine
but when i use all the operands I get something nasty,
Here is the example:
2*2/2+1-1
gets something like:
222/*11-+T_CHECKÖÐ7?█Ã
If you see, the expression is right until the 'T'
I believe it's some parameter mistake, so i'll put the header and return values here
1st)
char* convert(char *infix);
char *post = (char *)malloc(sizeof(char)*tamP);
return post;
2nd)
int evaluate(char *postfix)
while (*postfix != '\0')
return result;
Caller)
char* post = convert(infix);
result = evaluate(post);
Thanks
That kind of weird string looks more like a buffer overflow error. You are likely overwriting the null-terminator, so when the string is printed (or later used), it keeps going until it finds one, examining random program memory until it gets there.
Check that all of your string manipulations are correct.
It is possible that you are not adding the '\0' character at the end of 'post' (after the last sensible character) in the convert(char*) function. That's one reason I can think of.
Try setting the complete string to '\0' before you do anything with it:
memset(post, 0, tamP);
should do.

Resources