Following program with putw is not writing the required data in the file.
#include <stdio.h>
int main(void)
{
FILE *fp;
fp = fopen("a.txt", "w");
putw(25,fp);
putw(325,fp);
putw(425,fp);
fclose(fp);
return 0;
}
Program is compiled and executed like the following
gcc filename.c
./a.out
It is writing something in the file. Also if we read the integer using getw(), it is reading the value which is not available in the file. Even it is not the ASCII value.
When it is compiled with gcc filename.c -std=c99, it is showing implicit declaration warning error.
Is it required to link any library files to use putw/getw in c.
There is no function called putw in standard C, which is why you get compiler warnings. You probably meant to use putwc in wchar.h.
putw is an ancient function that exists on some platforms. Use fwrite and fread instead. You should also check the return value from putw. It may be telling you why it is failing.
Related
The text file is a list of words similar to this. each world is on a new line
When i run my code, the only thing being printed is "hi".... how do i get it to continue to read the next lines
hi
hello
welcome
#include <stdio.h>
#include <stdlib.h>
int main()
{
char data[100];
// OPENS THE FILE
FILE *fp = fopen("/classes/cs3304/cs330432/Programs/StringerTest/people.txt", "r");
if (fp == NULL)
{
printf("Unable to open the file\n");
} else {
fscanf(fp, "%s", data);
printf("%s", data);
fclose(fp);
}
}
How to get fscanf to scan the next Line in C
Read the documentation of fscanf. You cannot scan lines with it. And fscanf can fail, and you should handle its failure.
A possible approach is to read the next line using fgets (or getline, or readline) and later to parse it using sscanf.
Be also aware that in 2021, UTF-8 is used everywhere. So document on paper what your program should do if your people.txt file contains a line like Être ou ne pas être or a line with СТАРЫНКЕВИЧ (in Cyrillic letters).
If allowed, use a recent GCC compiler as gcc -Wall -Wextra -g (asking for all warnings and debug info), improve your code to get no warnings, and then use the GDB debugger to understand the behavior of your program. You could install Debian on your laptop to get gcc and gdb
The documentation of your program could use EBNF notation to specify what are the valid inputs.
Consider generating parts of your C code with tools like GNU bison.
When fopen fails you could use perror to report the error.
You may want to read the wikipage about recursive descent parsing.
You may want to study -for inspiration- the source code of GNU coreutils.
I am working on a simple program for learning purposes and I see the following behavior:
If I attempt to read an environment variable using getenv it works as expected:
#include <stdio.h>
#include <stdlib.h>
int main() {
printf("PATH is %s", getenv("PATH"));
return 0;
}
If I do not include stdlib.h, I get the expected warning:
env.c:7:26: warning: implicit declaration of function ‘getenv’; did you mean ‘getline’? [-Wimplicit-function-declaration]
The program still compiles. Running the program with the header runs as expected, the program without the header included gets a seg fault.
If I inspect the disassembly of both programs, I see that there is a call to getenv#PLT
call getenv#PLT
When I output the disassembly of the 2 programs (where the only difference in the c source code is the header include), the only difference I see is that when we include the header there's an instruction to set %eax to 0 before calling getenv.
movl $0, %eax
If I step through in gdb for the program without included header, it does jump into getenv and does run a whole lot of code within the c runtime.
I am wondering what is the exact reason why not including the header here causes this kind of behavior? Why does c let this compile?
Some info:
gcc version 7.4.0 (Ubuntu 7.4.0-1ubuntu1~18.04.1)
I am compiling like this:
gcc -O0 -S env.c
In C language, if you forget to include the header file, the getenv() function is interpreted as int getenv(...). If you include the header file, the getenv() function is interpreted as char* getenv(const char*). Because of implementation of printf() the only difference in your case is the size of the return value. If sizeof(int) == sizeof(char*), then you have no problem (this happens for 32-bit programs). If sizeof(int) != sizeof(char*), you get an error (this happens for 64-bit programs). This is explained in the comment #5
My C code was as following:
[Linux:/si/usr/hrl]vi test.c
#include <stdio.h>
FILE * hw = stdout;
int main(void)
{
return 0;
}
When I compile on SUSE , it make the error like that:
[Linux:/si/usr/hrl]cc test.c -o test
test.c:3: error: initializer element is not constant
I have a look for the header file stdio.h and find that stdout seems to have be defined as a constant. So why the error produce?By the way, I compile the same code on AIX ,it results of success.
The standard does not require stdin, stdout and stderr to be constants.
The draft n1256 for C99 says in 7.19.1 Input/output <stdio.h>
The header declares ...
...
TMP_MAX
which expands to an integer constant expression ...
stderr
stdin
stdout
which are expressions of type ‘‘pointer to FILE’’ ...
(emphasize mine)
It is explicitely stated that some other values are constant, whereas nothing is said for stdin, stdout and stderr
So you must put initialization in main:
#include <stdio.h>
FILE * hw;
int main(void)
{
hw = stdout;
...
return 0;
}
In AIX standard library, stdout happens to be a constant, but it is just an implementation detail and you cannot rely on that, as it could break in any newer version.
But you should not rely either on stdout being a variable (nor even a lvalue), because it is also an implementation detail in GCC library.
If you cannot change much of your code, and just need a GCC hack to make it compilable, you could try to use the gcc constructor attribute extension.
Extract from gcc documentation
6.31 Declaring Attributes of Functions
In GNU C, you declare certain things about functions called in your program which help the compiler optimize function calls and check your code more carefully.
The keyword __attribute__ allows you to specify special attributes when making a declaration. This keyword is followed by an attribute specification inside double parentheses. The following attributes are currently defined for functions on all targets: ... ,constructor, ...
...
The constructor attribute causes the function to be called automatically before execution enters main () ...
So you could use:
#include <stdio.h>
FILE * hw;
void initHw(void) __attribute__((constructor)) {
hw = stdout;
}
int main(void)
{
return 0;
}
But BEWARE: it is a gcc extension, meaning that your code is not correct C.
When I run the following command in the command terminal: gcc practice.c temp.txt
I get the following error:
/usr/local/binutils/2.21/bin/ld:temp.txt: file format not recognized; treating as linker script
/usr/local/binutils/2.21/bin/ld:temp.txt:1: syntax error
collect2: ld returned 1 exit status
Here is my C code:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAX_LEN 1024
int main(int argc, char **argv) {
FILE *file;
char line[MAX_LEN];
float value = 0;
file = fopen(argv[1], "r");
while (fgets(line, MAX_LEN, file) != NULL) {
sscanf(line, "%f", &value);
printf("%f\n", value);
}
fclose(file);
return 0;
}
Basically I am trying to read numbers in a file and just print them out. Very simple.
For example, temp.txt will just be something like:
10
26
27
52
242
(these numbers should be in a column)
and so forth.
You may need some explanation about what gcc really is, gcc is used to translate your code into a runnable program, it's a sort of translator for code to executable instruction for your computer.
You do not need to compile the text file, you first need to compile your program :
gcc practise.c -o your_binary_name
then launch it with your file in parameter :
./your_binary_name temp.txt
use gcc to compile the executable, and then run the executable on the input file afterwards. You get an error b/c gcc is trying to compile your test.txt as C source code.
So:
gcc practice.c -o practice
./practice test.txt
C is a compiled not an interpreted language. GCC does not run the code as say Python or other scripting languages can for example. GCC rather translates the C source code to native machine code that when linked to the target runtime to create an executable is then separately and directly loaded and executed by the operating system without support from GCC at all.
I'm writing some C code for an embedded linux system using an open_memstream and I don't understand why I am getting a compile warning: assignment makes pointer from integer without a cast
To make things simple, rather than pasting all my code I reproduced the problem with the small example from here:
#include <stdio.h>
#include <stdlib.h>
int
main (void)
{
FILE *stream;
char *buf;
size_t len;
off_t eob;
stream = open_memstream (&buf, &len);
if (stream == NULL)
/* handle error */ ;
fprintf (stream, "hello my world");
fflush (stream);
printf ("buf=%s, len=%zu\n", buf, len);
eob = ftello(stream);
fseeko (stream, 0, SEEK_SET);
fprintf (stream, "good-bye");
fseeko (stream, eob, SEEK_SET);
fclose (stream);
printf ("buf=%s, len=%zu\n", buf, len);
free (buf);
return 0;
}
The code works, but the compiler complains about the line stream = open_memstream (&buf, &len);
What integer is it talking about? We're passing in a pointer to a size_t as required by the function prototype.
FILE *open_memstream(char **bufp, size_t *sizep);
Is there a problem with this code, or do I need to take a look at my compiler? I want to get rid of this warning the right way.
UPDATE:
Using gcc 4.3.2, glibc 2.9
UPDATE 2:
Tried the following:
powerpc-860-linux-gnu-gcc -std=c99 -Wall -D_XOPEN_SOURCE=700 -c source.c
Result:
source.c: In function 'main':
source.c:12: warning: implicit declaration of function 'open_memstream'
source.c:12: warning: assignment makes pointer from integer without a cast
According to this, it seems that _XOPEN_SOURCE=700 is available since glibc 2.10.
Since I'm using glibc 2.9, what other alternatives do I have (other than upgrading glibc)?
UPDATE 3:
Adding the following got rid of the warning:
extern FILE *open_memstream(char **bufp, size_t *sizep);
Is there anything wrong with this solution?
UPDATE 4:
This worked instead of the extern:
powerpc-860-linux-gnu-gcc -std=c99 -Wall -D_GNU_SOURCE -c ops_cmds.c
So according to the manpage, need to use _GNU_SOURCE if glibc pre-2.10 (in my case) and _XOPEN_SOURCE=700 if 2.10+
Define:
#define _POSIX_C_SOURCE 200809L
or
#define _XOPEN_SOURCE 700
in your source code before including stdio.h. Or with gcc you can define and pass the macro value to the source file with -D option:
gcc -std=c99 -Wall -D_XOPEN_SOURCE=700 -c source.c
open_memstream is a POSIX function and its declaration is not visible in your program without this define.
The compiler is complaining about the return value of open_memstream, not about the arguments you pass in.
Your open_memstream is not declared, i.e. the compiler does not see the prototype. So the compiler (apparently pre-C99) assumes that it returns an int. You are forcing that int into stream pointer, which is what triggers the warning about "making pointer form integer".
Make sure open_memstream is declared before you attempt to use it. The prototype is supposed to reside in stdio.h, but it is only available in POSIX.1-2008. You have to enable it explicitly (see other answers).