the program is working when i am using getc but it is not working with this code.
I tried printing random text inside while loop it got printed with NULL.
void main()
{
FILE *fp;
char *str=NULL;
char s;
fp=fopen("text.txt","r");
if(fp==NULL)
{
printf("\nCAN NOT OPEN FILE");
exit(EXIT_FAILURE);
}
while(fscanf(fp,"%s",str)!=EOF)
{
printf("%s",str); //not taking any values in str,prints NULL
}
fclose(fp);
}
The problem is with this statement:
char *str=NULL;
Since you are using fscanf to read words which are character arrays, you have to read them into a valid memory location. So str should be a char array whose length should be equal to the longest word in your file plus 1 (for null termination).
So change the above to:
char str[256];
7.21.6.2 The fscanf function
...
12 The conversion specifiers and their meanings are:
s - Matches a sequence of non-white-space characters.
If no l length modifier is present, the corresponding argument shall be a
pointer to the initial element of a character array large enough to accept the
sequence and a terminating null character, which will be added automatically.
Here
char *str=NULL;
str is a pointer variable & it's initialized with NULL that's very fine but to store something into str i.e to read the word from file, and store into str it should have valid memory. So either allocate memory dynamically for str
str = malloc(SIZE); /* define SIZE */
Or use array of characters like
char str[100]; /* let say each word of file is less than 100 char's */
For e.g
char str[100];
while(fscanf(fp,"%s",str)!=EOF) {
printf("%s",str);
}
Also instead of void main() { } use
int main(void) {
/* some_code */
return 0;
}
as you can see from C Standard 5.1.2.2.1 Program startup.
Related
Problem Statement
Today is Newton School's first class of this year. Nutan, a student at
Newton School, has received his first assignment. He will be given a
string as input. His task is to print "Gravity'' if the input is
"Apple''; otherwise, he will have to print "Space''.
Can you help Nutan in solving his first assignment? Note that the
quotation marks are just for clarity. They are not part of the input
string, and should not be a part of your output string. Input The
input consists of a single line that contains a string S (1 ≤ length
of S ≤ 10). The string only consists of lowercase and uppercase
letters. Output Print "Gravity'' or "Space'' according to the input.
What I am trying to do:
Basically, I am taking a user-defined string and trying to compare it with the hard input string i.e "Apple". If both the string matches then it will print "Gravity" or else it will print "Space"
#include <stdio.h> // header file for Standard Input Output
#include <stdlib.h> // header file for Standard Library
#include <string.h> // for strcmp() function
int main() {
char str1[10]="Apple";
char str2[20];
int value;
printf("Enter the input ");
scanf("%s", &str2[20]);
value = strcmp(str1, str2);
if(value==0)
printf("Gravity");
else
printf("Space");
return 0;
}
scanf("%s", &str2[20]);
may invoke undefined behavior by out-of-range access. You should:
Pass the pointer to the first element of the array, not one to the next element of the last element. (most) arrays in expressions are automatically converted to pointes to their first elements.
Specify the maximum length to read to avoid buffer overrun.
Check if reading succeeded.
The line should be:
if (scanf("%19s", str2) != 1) {
puts("read error");
return 1;
}
Some improvements:
Don't use "%s", use "%<WIDTH>s", to avoid buffer-overflow
Instead of using bare return 0;, use return EXIT_SUCCESS;, which is defined in the header file stdlib.h.
always check whether scanf() input was successful or not
Use const char * instead of char str1[10]
There's no need for int value;
SYNTAX ERROR: &str2[20]
There's no need for passing the address of str2 READ MORE
Initialize str2 with zeroes
Add 1 more space in your str2 for NULL ('\0') terminating character
Final Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void) {
const char *str1 = "Apple";
char str2[21] = {};
printf("Enter the input ");
if(scanf("%20s", str2) != 1)
{
fprintf(stderr, "bad input\n");
return EXIT_FAILURE;
}
if(strcmp(str1, str2) == 0)
printf("Gravity");
else
printf("Space");
return EXIT_SUCCESS;
}
You are entering a string starting from the memory address after the last element of the array str2
scanf("%s", &str2[20]);
and then trying to compare the character array str1 with the non-initialized array str2
value = strcmp(str1, str2);
Change the call of scanf like
scanf("%19s", str2);
And the program will be safer if at least the array str2 will be initially initialized
char str2[20] = "";
Also as the array str1 is not changed then instead of the array you could declare a pointer to the string literal like
const char *str1 = "Apple";
And instead of the calls of printf
printf("Gravity");
//..
printf("Space");
it is better to use calls of puts
puts("Gravity");
//..
puts("Space");
Pay attention to that neither declaration from the header <stdlib.h> is used in your program. So you may remove this include directive
#include <stdlib.h> // header file for Standard Library
So, all I am trying to do is return a string from an array in a function to a variable in the main() function. Below is my function. It basically searches some files for a word, and returns the string name of the file that contains "START_ROOM":
char startPrompt()
{
//array of files
char* arrayFiles[7]={"Room1.txt", "Room2.txt", "Room3.txt", "Room4.txt", "Room5.txt", "Room6.txt", "Room7.txt"};
//used to store file that has START_FILE in it
char startFile;
int i;
for(i=0;i<7;i++)
{
//pointer to files
FILE *fPointer;
//prints files to output
char loadScreenOutput[800];
char* response[256];
fPointer=fopen(arrayFiles[i], "r");
//checks if the file doesn't exist
if(fPointer== NULL)
{
printf("Unable to open the file!\n");
}
//if file exists, do this.
else
{
while(!feof(fPointer))
{
fgets(loadScreenOutput, 800, fPointer);
if(strstr(loadScreenOutput, "START_ROOM"))
{
return *arrayFiles[i];
}
}
fclose(fPointer);
}
}
The main function is here:
int main()
{
char fileName;
//start the game with the start file
fileName=startPrompt();
printf("%s", fileName)
return 0;
}
Yet, the above leads to a segmentation fault.
If I change the printf to printf("%c", fileName), I will get the first letter of the file, which will be "R".
So, how can I simply get it to return "Room1.txt" and store it in fileName? I am willing to change the variable type of fileName, as I can guess that may be the issue. Or change the return type of the function, as I am guessing that is the issue.
Overwise, I know this code works because if I printf() inside the function, it will print "Room7.txt".
The code is a bit weird, but the main issue is that you expect a single character (i.e. char) to hold a "string", i.e. a sequence of characters. Strings in C are a sequence of characters terminated by special value 0; they are often used with pointers to string literals, written as char* someStringValue = "ABC":
char* str = "ABC"; // str will point to a sequence of characters {'A','B','C',0 }
char c = 'X'; // c will hold a single character 'X';
printf("%s",str); // will print ABC
printf("%s",c); // will probably segfault because c is not a pointer to a sequence of characters, i.e. is NOT A POINTER
printf("%c",c); // prints X
c = *str; // assignes the first character of the sequence to which str points
printf("%c",c); // prints A
To correct your program, write:
char* startPrompt() // char* instead of char; char would be a single character
{
// static; otherwise the variable and its values go out of scope and become invalid once startPrompt has finished
static char* arrayFiles[7]={"Room1.txt", "Room2.txt", "Room3.txt", "Room4.txt", "Room5.txt", "Room6.txt", "Room7.txt"};
...
return arrayFiles[i]; // not *arrayFiles[i], which would be a single character
...
int main() {
char* fileName; // char*, not char
fileName=startPrompt();
printf("%s", fileName)
return 0;
}
A string is actually an array of chars (which is also a pointer to a contiguous group of chars in memory). You need to make the function return a pointer to the first char in you array. Also "*" is not needed in the char array declaration (doing that creates a pointer to the pointer to the first char in the array).
I am going through The C Programming Language by K&R and trying to understand character pointers and arrays.
I am creating a function in C that reads multiple lines from stdin and stores the lines (char*) in an array of character pointers (char* []).
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
enum {MAXINPUT = 1024, MAXLINES = 100};
/* Reads at most `maxLines` lines and stores them in an array of char pointers. Returns number of lines read. */
int readlines(char* lineptr[], int maxLines);
/* Takes a single line input from stdin and stores it in str. Returns str length. */
int getInputLine(char* str, int maxInput);
int main(int argc, char** argv) { ... }
int readlines(char* lineptr[], int maxLines) {
/* Return number of lines read. */
int numLines = 0;
/* Buffer to store current line being read. */
char currentLine[MAXINPUT];
/* Terminate loop when enter is pressed at empty input or number of lines exceeds max. */
while(getInputLine(currentLine,MAXINPUT) && numLines < maxLines) {
/* Address of current line's first character is set to the appropriate index at lineptr. */
lineptr[numLines] = currentLine;
/* Both currentLine and lineptr[numLines] print accurately (note they are the same). */
printf("CURRENT LINE:\t %s\n",currentLine);
printf("lineptr[%d]:\t %s\n",numLines,lineptr[numLines]);
numLines++;
}
/* ISSUE: Outside the loop, lineptr does NOT print anything. */
printf("\nLOOPING\n");
for(int i = 0; i < numLines; i++) {
printf("%d: %s\n",i,lineptr[i]);
}
/* ISSUE: currentLine (which should be the last line entered) ALSO does not print outside the while. */
printf("\ncurrentLine: %s",currentLine);
return numLines;
}
My issue is that in the while(), the contents of lineptr and currentLine print accurately. But outside the while(), both lineptr and currentLine do not print anything.
And of course, this issue persists when I try to read lines into a char* [] in the main() and try to print its contents.
Why is it that the contents at the addresses being accessed by lineptr are printing inside the loop but not outside? Am I missing something obvious?
That's because you have a single buffer called currentLine into which you read text. Then you assign the address of currentLine to your lineptr[i], and proceed to overwrite its contents with new text. So, all your lineptrs essentially point to the same one location, which is the address of currentLine, and currentLine contains only the last line that you read. I suppose the loop does not print anything because the last line you read is empty.
So, to get this to work, you need to read a line into currentLine, measure its length, use malloc() to allocate enough memory for that line, copy the line from currentLine to the allocated memory, and store the pointer to the allocated memory in lineptr[i].
This line
lineptr[numLines] = currentLine;
just assigns a pointer to lineptr[numLines]. There are couple of issues with that:
Every line points to the same pointer.
The pointer is invalid after you return from the function.
You need to use something akin to:
lineptr[numLines] = strdup(currentLine);
Remember that strdup is not a standard C library function. If your platform does not support it, you can implement it very easily.
char* strdup(char const* in)
{
char* ret = malloc(strlen(in)+1);
return strcpy(ret, in);
}
I'm trying to get input from the user while allocating it dynamically and then "split" it using strtok.
Main Questions:
Im getting an infinite loop of "a{\300_\377" and ",".
Why do i get a warning of "Implicitly declaring library function "malloc"/"realoc" with type void"
Other less important questions:
3.i want to break, if the input includes "-1", how do i check it? As you can see it breaks now if its 1.
4.In the getsWordsArray() i want to return a pointer to an array of strings. Since i dont know how many strings there are do i also need to dynamically allocate it like in the getInput(). (I dont know how many chars are there in each string)
int main(int argc, const char * argv[])
{
char input = getInput();
getWordsArray(&input);
}
char getInput()
{
char *data,*temp;
data=malloc(sizeof(char));
char c; /* c is the current character */
int i; /* i is the counter */
printf ("\n Enter chars and to finish push new line:\n");
for (i=0;;i++) {
c=getchar(); /* put input character into c */
if (c== '1') // need to find a way to change it to -1
break;
data[i]=c; /* put the character into the data array */
temp=realloc(data,(i+1)*sizeof(char)); /* give the pointer some memory */
if ( temp != NULL ) {
data=temp;
} else {
free(data);
printf("Error allocating memory!\n");
return 0 ;
}
}
printf("list is: %s\n",data); // for checking
return *data;
}
void getWordsArray(char *input)
{
char *token;
char *search = " ,";
token = strtok (input,search);
while (token != NULL ) {
printf("%s\n",token);
token = strtok(NULL,search);
}
}
EDIT:
i noticed i forgot to "strtok" command so i changed it to token = strtok(NULL,search);
I still get wierd output on the printf:
\327{\300_\377
Change:
int main(int argc, const char * argv[])
{
char input = getInput();
getWordsArray(&input);
}
to:
int main(int argc, const char * argv[])
{
char *input = getInput();
getWordsArray(input);
}
with a similar to the return value of getInput():
char *getInput()
{
// ...
return data;
}
In your code, you were only saving the first character of the input string, and then passing mostly garbage to getWordsArray().
For your malloc() question, man malloc starts with:
SYNOPSIS
#include <stdlib.h>
For your getchar() question, perhaps see I'm trying to understand getchar() != EOF, etc.
Joseph answered Q1.
Q2: malloc and realoc returns type void *. You need to explicitly convert that to char *. Try this:
data = (char *) malloc(sizeof(char));
Q3: 1 can be interpreted as one character. -1, while converting to characters, is equivalent to string "-1" which has character '-' and '1'. In order to check against -1, you need to use strcmp or strncmp to compare against the string "-1".
Q4: If you are going to return a different copy, yes, dynamically allocate memory is a good idea. Alternatively, you can put all pointers to each token into a data structure like a linked list for future reference. This way, you avoid making copies and just allow access to each token in the string.
Things that are wrong:
Strings in C are null-terminated. The %s argument to printf means "just keep printing characters until you hit a '\0'". Since you don't null-terminate data before printing it, printf is running off the end of data and just printing your heap (which happens to not contain any null bytes to stop it).
What headers did you #include? Missing <stdlib.h> is the most obvious reason for an implicit declaration of malloc.
getInput returns the first char of data by value. This is not what you want. (getWordsArray will never work. Also see 1.)
Suggestions:
Here's one idea for breaking on -1: if ((c == '1') && (data[i-1] == '-'))
To get an array of the strings you would indeed need a dynamic array of char *. You could either malloc a new string to copy each token that strtok returns, or just save each token directly as a pointer into input.
I am new to programming and have faced this particular problem:
int *FindLine(char *lines[100],int line_number) {
char **pointer=lines;
int i,*stack,counter=0;
stack=(int*)calloc(30,sizeof(int));
for (i=0;i<line_number;i++)
if (*pointer[i]=='{') {
stack[counter]=i+1;
counter++;
}
return stack;
}
main(){
char *line[100];
FILE *fp;
char FileName[20];
char Buffer[100];
fp=fopen(FileName,"r");
while(fgets(Buffer,100,fp)!=NULL) {
line[i]=strdup(Buffer);
i++;
}
NumOfLines=i;
Stack=FindLine(line,NumOfLines);
system("PAUSE");
}
stack is supposed to have stored the number of the line each '{' appears in , instead it only stores it if '{' is the first char on the line. is there a way on C to access every single individual character of the strings pointed by the pointers in the array of pointers to strings ?
Change
if (*pointer[i]=='{')
to
if (!strchr(pointer[i],'{'))
You may need to add
#include <string.h>
at the beginning.
pointer[i] points to the string (array of chars).
*pointer[i] gives you the first character of the string.
So your if condition checks only the first character.
So you have to use strchr
strchr checks if the '{' char is there anywhere in the string. returns the pointer to first occurance if found or 0/NULL if not found.