I have this little problem, and can't solve it.
The thing is that I'm trying to load all four strings in the function LOAD by asking the user to insert it. Everything seems fine and I don't get any compiler error. But eaf stays empty. I tried many ways, even replacing scanf with gets, gets_s, fgets, but nothing changes.
#include <conio.h>
#include <stdio.h>
#include <string.h>
void LOAD(char eaf[], char initials[], char finals[], char symbols[]);
int COMPARE(char s[], char eaf[]);
int main()
{
char eaf[10],initials[1],finals[10],symbols[5];
LOAD(eaf, initials, finals, symbols);
return 0;
}
void LOAD(char eaf[], char initials[], char finals[], char symbols[])
{
printf("Insert states of the optimized AFD\n");
scanf( " %s", eaf);
printf("Insert AFD initial state\n");
do
{
scanf( " %s", initials);
} while (COMPARE(initials, eaf));
printf("Insert final state(s)\n");
do
{
scanf( " %s",finals);
} while (COMPARE(finals, eaf));
printf("Insert the language symbols\n");
scanf( " %s",symbols);
}
int COMPARE(char s[], char eaf[])
{
int i;
char *ptr;
for(i; i < strlen(s); i++){
printf("%d\n", i);
while(ptr==NULL){
ptr = strchr(eaf, *s);
}
}
if (ptr == NULL) return 1;
else return 0;
}
What am I doing wrong? This is just a small part of a bigger program, but the rest of it is useless because eaf is empty. I thought that the problem was using scanf, but as I said other functions didn't work as well. I hope anyone can help me. Thanks
edit: I checked by strlen(eaf)
Using "scanf" for input is dangerous, and you've walked right into that danger. You're allowing it to overwrite the contents of "eaf" when you ask it to read initials as a string and it adds the terminating 0.
Ultimately, the string is empty because you got your array dimensions wrong. You gave "initials" an array size of 1 which does not provide space for the trailing '\0' C-string terminator.
See the live demo of this code on ideone:
#include <stdio.h>
void report(char* eaf, char* initials, char* foo)
{
printf("eaf = %p, initials = %p, foo = %p\n", eaf, initials, foo);;
printf("*eaf = %d, *initials = %d, *foo = %d\n", eaf[0], initials[0], foo[0]);
}
void load(char eaf[], char initials[], char foo[])
{
printf("load\n");
report(eaf, initials, foo);
printf("Enter EAF\n");
scanf(" %s", eaf);
report(eaf, initials, foo);
printf("Enter initial state\n");
scanf(" %s", initials);
report(eaf, initials, foo);
}
int main(int argc, const char* argv[])
{
char eaf[10], initials[1], foo[10];
report(eaf, initials, foo);
load(eaf, initials, foo);
report(eaf, initials, foo);
return 0;
}
You should have walked thru this in the debugger and watched the values of "eaf" and "initials" to see what happened as you progressed.
Do you have to write this program in C? It seems that using a scripting language such as perl or python might be easier for you.
Here is a working C method to start solving the problem, note that I didn't actually fix the problem, but it will make it easier to see it.
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <string.h>
void report(char* eaf, char* initials, char* foo)
{
printf("eaf = %p, initials = %p, foo = %p\n", eaf, initials, foo);;
printf("*eaf = %d, *initials = %d, *foo = %d\n", eaf[0], initials[0], foo[0]);
}
void load(const char* label, const char* into, size_t intoSize)
{
assert(intoSize > 1); // can't store a string in 1 character.
printf("%s\n", label);
char input[1024] = "";
fgets(input, sizeof(input), stdin);
size_t len = strlen(input);
// strip trailing \n off.
if (len > 0 && input[len - 1] == '\n') {
input[--len] = 0;
}
// abort on empty input
if (len <= 0) {
fprintf(stderr, "Invalid input - terminated.\n");
exit(1);
}
if (len >= intoSize) {
fprintf(stderr, "Invalid input - length was %u, limit is %u\n", len, intoSize - 1);
exit(2);
}
strncpy(into, input, intoSize);
}
int main(int argc, const char* argv[])
{
char eaf[10], initials[1], foo[10];
report(eaf, initials, foo);
load("Insert states of the optimized AFD", eaf, sizeof(eaf));
report(eaf, initials, foo);
load("Insert initial AFD state", initials, sizeof(initials));
report(eaf, initials, foo);
printf("eaf = %s\ninitials = %s\n", eaf, initials);
return 0;
}
See live demo on ideone here.
You're format string in scanf is most likely the culprit; you have an extra space before the %s.
Change:
scanf( " %s", eaf);
to
scanf( "%s", eaf);
for all your scanf's.
Its not putting your input into eaf because it is looking for a string of the format " blahblahblah" (note the space in the beginning) instead of "blahblahblah"
Edit
Disregard the above,
whitespace: Any whitespace characters trigger a scan for zero or more whitespace characters. The number and type of whitespace characters do not need to match in either direction.
Also, you should initialize i in your COMPARE function (I don't understand how you're not getting an angry warning from your compiler), I ran your code with no modifications and strlen(eaf) returned the correct count (just after the scanf).
Related
So I have this super simple C code here taking a user input and prints it out followed by a "T-Plus" while loop. In this case I chose a random name for testing "whoa", but the while loop is not called. My question is, why does the "T-Plus: %d\n" while loop print not be called after the printf() function?:
#include <stdio.h>
char getString();
void tcount(void);
int main(void)
{
tcount();
}
void tcount(void)
{
// class scanf user input
printf("%s", getString());
int i = 1;
do
{
printf("T-Plus: %d\n", i);
i++;
} while( i < 51 );
}
char getString()
{
char name;
printf("Please a string name: \n");
scanf("%s", &name);
return name;
}
Now when I run it, this becomes the output:
$ ./namecount
Please a string name:
whoa
but the T-Plus: string does not get called.
I see two issues here:
1) In function getString() you are trying to read/scan a string in a char, you need memory to store the string and a terminating char, so you can use either of these two ways
Use a char array e.g. char name[50]; or
Use a char pointer and
allocate memory using malloc e.g.
char *p_name = malloc(sizeof(char)*50);
2) You are then trying to return this string which is stored in local variable (which would get destroyed as soon as function ends) so you should use the second approach (use malloc) and return the pointer.
So your code would look like:
#include <stdio.h>
#include <stdlib.h>
char * getString();
void tcount(void);
int main(void)
{
tcount();
}
void tcount(void)
{
// class scanf user input
char *p_name = getString();
printf("%s", p_name);
free(p_name);
int i = 1;
do
{
printf("T-Plus: %d\n", i);
i++;
} while( i < 51 );
}
char *getString()
{
char *p_name = malloc(sizeof(char)*50);
printf("Please a string name: \n");
scanf("%s", p_name);
return p_name;
}
Above answer did not work, Okay so I've edited the code like this, it compiles fine. But raises a segmentation fault though.
#include <stdio.h>
#include <stdlib.h>
char * getString();
void tcount(void);
int main(void)
{
tcount();
}
void tcount(void)
{
// class scanf user input
char *name = getString();
printf("%s", name);
free(name);
int i = 1;
do
{
printf("T-Plus: %d\n", i);
i++;
} while( i < 51 );
}
char * getString()
{
char *p_name[50];
printf("Please a string name: \n");
scanf("%49s", (char *) &p_name);
return *p_name;
}
When the program is run, it asks for your input but still raises a Segmentation fault (core dumped).
My program skips the next input after 1 pass through it. I have read the threads on removing the newline character that fgets has, but nothing that was suggested worked. Is there anything that would work with microsoft visual studio? The best suggestion was "words[strcspn(words, "\r\n")] = 0;" and this did not remove the new line, unless I am formatting it incorrectly. I am not allowed to use the strtok function.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SIZE 50
#define STOP "quit\n"
char *copywords(char *dest, const char *source, size_t n);
int main(void)
{
char words[50];
char newwords[50];
size_t num;
for (;;) {
printf("\nType a word, or type 'quit' to quit: ");
(fgets(words, SIZE, stdin));
if (strcmp(words, STOP) == 0) {
printf("Good bye!\n");
return 0;
}
printf("Type the # of chars to copy: ");
scanf_s("%d", &num);
copywords(newwords, words, num);
printf("The word was %s\n", words);
printf("and the copied word is %s", newwords);
}
}
char *copywords(char *dest, const char *source, size_t n) {
size_t i;
for (i = 0; i < n && source[i] != '\0'; i++) {
dest[i] = source[i];
}
dest[i] = '\0';
return dest;
}
The problem is that you leave the \n on the input when you call scanf. i.e. the user types number[return]. You read the number. When you loop around and call fgets agains the return is still waiting to be read so thats what fgets gets and it returns immediately.
I would probably just call fgets the second time you want to read input as well and then use sscanf to read from the string. i.e.
printf("Type the # of chars to copy: ");
fgets(buffer, ...)
sscanf(buffer, "%d", ...)
As an aside I would also say to check return values as it is easy for fgets or *scanf to fail.
My program skips the next input after 1 pass through it.
If I understand you correctly, the problem is that scanf_s (which I assume is like the C standard's scanf) will read the digits into num, but scanf won't remove the following newline from stdin, and so in the next iteration of the loop fgets will see that newline and behave as if it had seen a blank line.
I have usually avoided scanf for this reason and instead read a line into a buffer and then parse it. For example:
char buf[50];
...
fgets(buf,sizeof(buf),stdin);
sscanf(buf,"%d",&num);
(I'd also recommend adding a whole lot more error checking throughout.)
Here's a straightforward solution.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SIZE 50
#define STOP "quit\n"
char *copywords(char *dest, const char *source, size_t n);
int main(void)
{
char words[50];
char newwords[50];
size_t num, run = 0;
for (;;) {
printf("\nType a word, or type 'quit' to quit: ");
if(run)
getchar();
(fgets(words, SIZE, stdin));
if (strcmp(words, STOP) == 0) {
printf("Good bye!\n");
return 0;
}
printf("Type the # of chars to copy: ");
scanf("%d", &num);
copywords(newwords, words, num);
printf("The word was %s\n", words);
printf("and the copied word is %s", newwords);
run = 1;
}
}
char *copywords(char *dest, const char *source, size_t n) {
size_t i;
for (i = 0; i < n && source[i] != '\0'; i++) {
dest[i] = source[i];
}
dest[i] = '\0';
return dest;
}
Since we know there will be an extra '\n' character left in the stream due to the scanf, just take it out.
I am learning C and I simply wanted to output the first char of the string that the user inputs. Somehow it doesnt work? I also got no error message. This must be a really simple question, but I dont get it.
#include <stdio.h>
int main(void)
{
char input[200];
char test;
printf("Text input: ");
scanf("%s", input);
test = input[0];
printf("%s", test);
return 0;
}
You need to use %c to print a char. %s is for null-terminated strings, i.e. char arrays. The code below works fine for me.
#include <stdio.h>
int main() {
char input[200];
char test;
printf("Text input: ");
scanf("%s", input);
test = input[0];
printf("%c\n", test);
return 0;
}
Try this
#include <stdio.h>
int main() {
char input[200];
char test;
printf("Text input: ");
scanf("%s", input);
test = input[0];
printf("%c\n", test);
return 0;
}
This works. U need to use %c rather than %s to print characters
I’m trying to get the _strrev function to work but when I put my string into a function it doesn’t seem to work, just when I'm out of the function..
I’m getting so frustrated because I'm not getting anywhere with this..
Here's my code so far
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void reverse(char *string) {
char *str, temp;
int begin = 0, end = 0;
char word[64];
int jaja = 0;
printf("Your string from the function is %s\n", string);
printf("%s\n", _strrev(&string)); //And why isnt this working
jaja = strlen(string);
printf("Your string has %d characters\n", jaja);
}
int main()
{
char *str;
scanf("%s", &str);
printf("%s\n", _strrev(&str)); //How come this works
reverse("Okay");
getchar();
return(0);
}
So I would love some guidance where my mistake is, I seriously cant find it.
According to MSDN The prototype for _strrev is
char *_strrev(
char *str
);
If you have a char *string you must call it like this :
printf("%s\n", _strrev(string));
In this case
printf("%s\n", _strrev(&string));
you are passing a char**
To answer the question you posted in your code comments:
int main()
{
char *str;
scanf("%s", &str);
printf("%s\n", _strrev(&str)); //How come this works
That works because you're lucky, as your call to scanf() places whatever it reads into the actual memory used for the pointer str, and you're not entering enough data to cause problems. Try entering a really long string when running this program and it won't work as well.
You need to actually have a char buffer to read data into, like this:
int main()
{
char str[256];
scanf("%s", str);
printf("%s\n", _strrev(str));
or
int main()
{
char *str = malloc( 256 );
scanf("%s", str);
printf("%s\n", _strrev(str));
And as pointed out in the comments to the question, you can still overrun your buffer.
#include <stdio.h>
#include <math.h>
#include <string.h>
int main(void)
{
int menuswitch=1;
int amountofstudents;
int fname[50];
int lname[50];
int grade[50];
int i;
char studentinfo[100];
printf("Enter Amount of Students: ");
scanf("%d", &amountofstudents);
for (i=0;i<amountofstudents;i++)
{
gets(studentinfo);
strcpy(fname[i], strtok(studentinfo, " "));
strcpy(lname[i], strtok(NULL, " "));
strcpy(grade[i], strtok(NULL, " "));
}
Alright need a little using strtok. I am trying to store pieces of an input string to sort later. I was thinking of using strtok to break the string then placing each piece in the corresponding array. Yet, every time I try I get an error in Visual Studios saying Access Violation. Thanks for the help ahead of time
The error is
First-chance exception at 0x5120F7B3 (msvcr110d.dll) in Lab 2.exe: 0xC0000005: Access violation reading location 0x00000000.
Unhandled exception at 0x5120F7B3 (msvcr110d.dll) in Lab 2.exe: 0xC0000005: Access violation reading location 0x00000000.
The input would be
FirstName Lastname 80(Grade)
One major problem is that you try to copy into integer values and not strings. Change the
integer arrays to arrays of strings:
...
char fname[50][100];
char lname[50][100];
char grade[50][100];
...
You also have a problem with the gets function (besides it being obseleted and should not be used), namely that the previous scanf doesn't remove the newline from the input buffer so the first gets call will see this empty newline and give you an empty line (which you do not check for).
This is simply solved by telling scanf to discard trailing whitespace by adding a space in the format string after the "%d":
scanf("%d ", &amountofstudents);
/* ^ */
/* | */
/* Note space */
Instead of gets, you should be using fgets:
fgets(studentinfo, sizeof(studentinfo), stdin);
And finally, always check for errors!
a potential issue is the scanf/gets combo. use instead fgets() and convert when appropriate to integer using atoi() it is also good to do a sanity check on what is returned from strtok (it is never good to assume anything about input)
char* token = strtok(studentinfo, " ");
if ( strlen(token) < sizeof(fname[i]) )
{
strcpy(fname[i], token);
...
you have also declared your strings as integer arrays, they should be char
e.g. char fname[50];
The problem you have is that you have declared three variables (fname, lname, and grade) as char[] (arrays) (well, that is the type you meant to use), but you want to prompt for and keep around a bunch of students information. And you later try to copy from strtok() into what you want to be a char[], but since you dereferenced fname[i] (lname[i], grade[i]), they are of type char, rather than char[].
You will need stdlib.h for exit,
#include <stdio.h>
#include <stdlib.h> //for exit
#include <string.h>
//#include <math.h> //you don't need this, yet
#define STUDLIMIT (100)
You can either create an array of fname[], lname[], grade[], (see here: http://www.cs.swarthmore.edu/~newhall/unixhelp/C_arrays.html),
int main(void)
{
//int menuswitch=1; //you aren't using this
int amountofstudents;
char studentinfo[100];
char fname[STUDLIMIT][50];
char lname[STUDLIMIT][50];
char grade[STUDLIMIT][50];
int ndx;
printf("Enter Amount of Students: ");
if( (fscanf(stdin,"%d ", &amountofstudents)<=0)
|| (amountofstudents<1) || (amountofstudents>STUDLIMIT) )
{
printf("need %d to %d studends\n",1,STUDLIMIT); exit(0);
}
for (ndx=0;ndx<amountofstudents;ndx++)
{
printf("Student: "); fflush(stdout);
fgets(studentinfo,sizeof(studentinfo),stdin);
strcpy(fname[ndx], strtok(studentinfo, " "));
strcpy(lname[ndx], strtok(NULL, " "));
strcpy(grade[ndx], strtok(NULL, " "));
}
}
Or you can create a struct(ure) to hold the entered student information, and instantiate an array of these student records, one for each student you enter and store,
typedef struct student
{
char fname[50];
char lname[50];
char grade[50];
} StudentObj;
int StudentCopy(StudentObj*sp,char*fname,char*lname,char*grade)
{
if(!sp || !fname || !lname || !grade ) return -1;
strcpy(sp->fname, fname);
strcpy(sp->fname, lname);
strcpy(sp->fname, grade);
}
StudentObj students[STUDLIMIT];
int main(void)
{
//int menuswitch=1; //you aren't using this
int amountofstudents;
char studentinfo[100];
char fname[50];
char lname[50];
char grade[50];
int ndx;
printf("Enter Amount of Students: ");
if( (fscanf(stdin,"%d ",&amountofstudents)<=0)
|| (amountofstudents<1) || (amountofstudents>STUDLIMIT) )
{
printf("need %d to %d studends\n",1,STUDLIMIT); exit(0);
}
for (ndx=0;ndx<amountofstudents;ndx++)
{
printf("Student: "); fflush(stdout);
fgets(studentinfo,sizeof(studentinfo),stdin);
strcpy(fname, strtok(studentinfo, " "));
strcpy(lname, strtok(NULL, " "));
strcpy(grade, strtok(NULL, " \n\r"));
StudentCopy(&(students[ndx]),fname,lname,grade);
}
}