when I'm trying to compile the example on the nongnu avr user manual, I get an error:
Here's the example:
#include <stdio.h>
static int uart_putchar(char c, FILE *stream);
static FILE mystdout = FDEV_SETUP_STREAM(uart_putchar, NULL,
_FDEV_SETUP_WRITE);
static int
uart_putchar(char c, FILE *stream)
{
if (c == '\n')
uart_putchar('\r', stream);
loop_until_bit_is_set(UCSRA, UDRE);
UDR = c;
return 0;
}
int
main(void)
{
init_uart();
stdout = &mystdout;
printf("Hello, world!\n");
return 0;
}
When I try to compile it, I get errors that UDR, UCSRA, UDRE, and loop_until_bit_is_set are undeclared. Why is this happening?
Thanks!
I solved it by also including <avr/io.h>, adding some of the names, and implementing the init_uart function.
Related
Hello,
I'm trying to write a linux module that can be able to read a file line by line and stock each line in
a corresponding column of an array.
For example if my file contains those following lines:
1
10
20
,I would like to read this file with kernel functions like kernel_read(...) and insert
each line in one corresponding column of my array such as tab[0] = 1, tab[1] = 10 and tab[2] = 20;
When tab[3] is the array to receive the file's content.
I have already this code but I get the content of line character by character no all the line at same time.
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/syscalls.h>
#include <linux/fcntl.h>
#include <asm/uaccess.h>
#include <linux/slab.h>
#include <linux/string.h>
MODULE_LICENSE("GPL");
char *tab; //the table to contain each line the file
char tmp[10];
static int i=0;
static void read_file(char *filename)
{
struct file *f = NULL;
int fd;
char buf[1];
loff_t f_pos = 0;
mm_segment_t old_fs = get_fs();
tab = kmalloc(15, GFP_KERNEL);
set_fs(KERNEL_DS);
f = filp_open(filename, O_RDONLY, 0);
if (!IS_ERR(f)) {
printk(KERN_DEBUG);
while (kernel_read(f, buf, 1, &f_pos) == 1){
printk("%c", buf[0]);
if(buf[0]!='\n'){
tab[i]=buf[0];
printk("tab[%d] = %c", i, tab[i]);
i++;
}
}
printk("\n");
//sys_close(fd);
filp_close(f, NULL);
}
set_fs(old_fs);
}
static int __init init(void)
{
read_file("myfile.txt");
return 0;
}
static void __exit exit(void)
{ }
module_init(init);
module_exit(exit);
The above code give me character by character on each line.
For example if the value of the line is 10, I can not get 10 but 1 and after 0;
I can do it with C language standard functions in user space.
As it is no able to use them in kernel space, How can I do to be able to insert the content of each lines in columns of the receiving array?
Can help me, please ?
I already know that reading file from kernel is not recommended but I need to do this for some tests.
I'm pretty new to C, and I'm not sure what is wrong with this piece of code I have written. It is supposed to open (or create if needed) a file using a name specified and in that file write a bunch of signs taken from the /dev/urandom file. I need a precise amount of elements each one of a specified length. I need to be able to later edit that created file, but I wanted to focus on creating this generator part first. It doesn't show any errors when compiling or when I try to execute it, but still nothing happens - the file still doesn't exist anywhere. What's wrong with it?
int main(){
void generate(char str[], int a, int b);
}
void generate(char str[], int a, int b){
int n=0;
char fname[128];
strcpy(fname,str);
strcpy(fname, ".txt");
FILE *myFile = fopen(fname, "w");
FILE *randomiser = fopen("/dev/urandom", "r");
char bufor[a];
size_t result = fread (bufor, b, a, randomiser);
size_t end = fwrite (bufor, b, a, myFile);
fclose(myFile);
fclose(randomiser);
}
#edit
change the tile as someone suggested and changed a code a bit since im still trying to work it out
I forgot to mention that the whole point of this function is for it to be called in terminal as for example ./program generate data 100 100.
Here is the exact solution you asked for
There you go. I use open instead of fopen, read a certain amount of char out of /dev/urandom then write it to fd2 (the file created),
Be carefull the size of the buffer, be careful The NULL (\0) terminate the string
#include <sys/types.h>
#include <sys/uio.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
int generate(char **av)
{
int fd1 = open("/dev/urandom", O_RDONLY);
int fd2 = open(av[1], O_CREAT | O_RDWR, S_IRWXU);
int size = atoi(av[2]);
int row = atoi(av[3]);
int i = -1;
int j = -1;
if (fd1 == -1 || fd2 == -1 || size <= 0 || row <= 0 )
return (1);
char buf[size];
while (++i < row-1)
{
read(fd1, buf, size);
buf[size -1] = '\0';
write(fd2, buf, size -1);
while (++j < size)
buf[j] = '\0';
}
close(fd1);
close(fd2);
return (0);
}
int main(int ac, char **av)
{
int s;
if (ac < 4)
return (1);
generate(av);
return (0);
}
for 10 * 100 char into file 'blabla' Use with :
$~> gcc prog.c -o program
$~> ./program blabla 100 10
Will create / open the file "blabla" read 100 from /dev/uramdom and wirte to blabla
To explain what you did wrong here look :
This is a declaration of a function
void generate(int i, char *a);
This is a call to a function
generate(25, "Blablabla");
sometime when you declare a function you also instanciate it aswell
int generate(int i, char *a)
{
Operation;
operation;
return (0);
}
Declaration, and instanciation are different, let's assume i wrote funtion generate under function main in the above code example, function main would not know what is "generate" but if you declare it before main just like this it works
void generate(int i, char *a);
Here's what I made out of your source code with minimal changes
#include <stdio.h>
void generate(char basename[], size_t size);
int main(void) {
generate("foobar", 42);
}
void generate(char basename[], size_t size) {
char fname[128];
sprintf(fname, "%s.txt", basename);
FILE *myFile = fopen(fname, "w");
FILE *randomiser = fopen("/dev/urandom", "r");
char bufor[size];
size_t result = fread(bufor, 1, size, randomiser);
fwrite(bufor, 1, result, myFile);
fclose(myFile);
fclose(randomiser);
}
The problem is that your program never calls the generate() function, as #fredrik pointed out in comments. This:
void generate(char str[], int a, int b);
is a function declaration, not a call. Although it is legal to put such a declaration inside a function, it is much more conventional to put it outside and preceding the function(s) that will be doing the calling. And in this case, you could avoid using a separate declaration at all by just moving the main() function to the end, after the definition of generate().
But that still doesn't get around the fact that you need to call the function if you want it to do anything. And to call it, you will need to provide arguments. For example,
generate("random_data", 10, 4);
From your description, you'll want to use arguments determined from evaluation of command-line parameters, but that aspect would be a separate question.
Is there any way to create a memory buffer as a FILE*. In TiXml it can print the xml to a FILE* but i cant seem to make it print to a memory buffer.
There is a POSIX way to use memory as a FILE descriptor: fmemopen or open_memstream, depending on the semantics you want: Difference between fmemopen and open_memstream
I guess the proper answer is that by Kevin. But here is a hack to do it with FILE *. Note that if the buffer size (here 100000) is too small then you lose data, as it is written out when the buffer is flushed. Also, if the program calls fflush() you lose the data.
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
FILE *f = fopen("/dev/null", "w");
int i;
int written = 0;
char *buf = malloc(100000);
setbuffer(f, buf, 100000);
for (i = 0; i < 1000; i++)
{
written += fprintf(f, "Number %d\n", i);
}
for (i = 0; i < written; i++) {
printf("%c", buf[i]);
}
}
fmemopen can create FILE from buffer, does it make any sense to you?
I wrote a simple example how i would create an in-memory FILE:
#include <unistd.h>
#include <stdio.h>
int main(){
int p[2]; pipe(p); FILE *f = fdopen( p[1], "w" );
if( !fork() ){
fprintf( f, "working" );
return 0;
}
fclose(f); close(p[1]);
char buff[100]; int len;
while( (len=read(p[0], buff, 100))>0 )
printf(" from child: '%*s'", len, buff );
puts("");
}
C++ basic_streambuf inheritance
In C++, you should avoid FILE* if you can.
Using only the C++ stdlib, it is possible to make a single interface that transparently uses file or memory IO.
This uses techniques mentioned at: Setting the internal buffer used by a standard stream (pubsetbuf)
#include <cassert>
#include <cstring>
#include <fstream>
#include <iostream>
#include <ostream>
#include <sstream>
/* This can write either to files or memory. */
void write(std::ostream& os) {
os << "abc";
}
template <typename char_type>
struct ostreambuf : public std::basic_streambuf<char_type, std::char_traits<char_type> > {
ostreambuf(char_type* buffer, std::streamsize bufferLength) {
this->setp(buffer, buffer + bufferLength);
}
};
int main() {
/* To memory, in our own externally supplied buffer. */
{
char c[3];
ostreambuf<char> buf(c, sizeof(c));
std::ostream s(&buf);
write(s);
assert(memcmp(c, "abc", sizeof(c)) == 0);
}
/* To memory, but in a hidden buffer. */
{
std::stringstream s;
write(s);
assert(s.str() == "abc");
}
/* To file. */
{
std::ofstream s("a.tmp");
write(s);
s.close();
}
/* I think this is implementation defined.
* pusetbuf calls basic_filebuf::setbuf(). */
{
char c[3];
std::ofstream s;
s.rdbuf()->pubsetbuf(c, sizeof c);
write(s);
s.close();
//assert(memcmp(c, "abc", sizeof(c)) == 0);
}
}
Unfortunately, it does not seem possible to interchange FILE* and fstream: Getting a FILE* from a std::fstream
You could use the CStr method of TiXMLPrinter which the documentation states:
The TiXmlPrinter is useful when you
need to:
Print to memory (especially in non-STL mode)
Control formatting (line endings, etc.)
https://github.com/Snaipe/fmem is a wrapper for different platform/version specific implementations of memory streams
It tries in sequence the following implementations:
open_memstream.
fopencookie, with growing dynamic buffer.
funopen, with growing dynamic buffer.
WinAPI temporary memory-backed file.
When no other mean is available, fmem falls back to tmpfile()
I am new in C. I want to create a file in linux C program and write environment variables in it. If file already exist I want to open and append. I have written the following code.
char *envFile=getenv("FILENAME");
int fdEnv=-1;
fdEnv=open(envFile,O_CREAT,O_RDWR,O_APPEND);
printf("%d",fdEnv);
char** env;
if(fdEnv>0)
{
for (env = environ; *env != 0; env++)
{
char *thisEnv = *env;
printf("%s",thisEnv);
write(fdEnv,thisEnv,strlen(thisEnv));
}
close(fdEnv);
}
But when I run it first time. A blank file is created. And it stays locked after execution. Looks like some error. Second time it fdEnv stays less than 0.
I really don't understand what is happening here. Please help.
Try using | to separate the flags.
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
extern char **environ;
int main(void)
{
char *envFile = getenv("FILENAME");
int fdEnv = -1;
fdEnv = open(envFile, O_CREAT|O_RDWR|O_APPEND, 0644);
printf("%d\n", fdEnv);
int i = 0;
while (environ[i]) {
printf("%s\n", environ[i]);
write(fdEnv, environ[i], strlen(environ[i]));
char lf = '\n';
write(fdEnv, &lf, 1);
i++;
}
close(fdEnv);
return 0;
}
I've run above code on my linux computer and it works.
extern char **environ;
int main()
{
char **env;
char* filename = getenv("FILENAME")
const char* mode = "a";
FILE* file = fopen( filename, mode );
for ( env = environ; *env; ++env )
fprintf( file, "%s\n", *env );
fclose(file);
return(0);
}
You should think about handling when getenv fails, is blank, etc; let me know if you have any questions.
I have a segmentation fault...i'm not sure what's causing it. Also, when passing the member pname into the function get_names, am I doing this correctly, or is there a better way of doing this?
#include <stdio.h>
#define MAX_NAME 20
#define MAX_PLAYRS 16
typedef struct {
char pname[MAX_NAME];
int runs;
char how_out;
} Team_t;
Team_t player[MAX_PLAYRS];
Team_t *player_ptr[MAX_PLAYRS];
void get_names (int count, char *str);
int main (void) {
int i;
for (i = 0; i < MAX_PLAYRS; i++) {
get_names(i, &(*player[i].pname));
printf("Player: %s\n", player[i].pname);
}
}
void get_names (int count, char *str) {
FILE *inp;
char status;
inp = fopen("teamnames.rtf", "r");
status = fscanf(inp, "%s", str);
if (status == EOF) {
count = MAX_PLAYRS;
}
}
With your code unchanged, I get a segmentation fault if the file can't be opened properly (i.e. it's unreadable due to permissions, or it simply does not exist).
Here's a modified version of you function get_names():
void get_names(int count, char *str)
{
FILE *inp;
inp = fopen("teamnames.rtf", "r");
if (inp == NULL) {
perror("Failed");
return;
}
fgets(str, MAX_NAME, inp);
fclose(inp);
}
This would still read the first name 16 times, but it would tell you why it didn't manage to open the file. To read the next name from the file (rather than repeatedly the first name), open (and close) the file in the main() function instead.
Also, you might as well call get_names() like so:
get_names(i, player[i].pname);
No need to do that &(*...) thing you're doing.
And, finally, I hope that the teamnames.rtf file is not actually an RTF file, but a simple text file with a name on each line.
The problem comes from this line:
get_names(i, &(*player[i].pname));
Understanding pointers and dereferencing is one of the biggest adjustments to learning C if you are switching from another language. You're doing it wrong, and I think you should seek out a tutorial on the subject. Try http://www.cplusplus.com/doc/tutorial/pointers/ as a starting point.
Get a debugger to tell you what is wrong. Compile the code with debugging enabled (see you man page for your compiler) and run something like this:
gdb a.out core
Then you should be able to see which line made the code core dump. You could use idb as well, if you have the intle compiler installed. This is, of course, on *nix. If you are talking windows, use the VS debugger.
In addition do NOT use fscanf as it is unsafe. Use fgets instead.
There are many strange things. First thing is, it seems like the names are in a file, but what you are doing is in every iteration of your for loop, you call get_names which opens the file again, that is goes to the beginning of the file and you read the same name over and over again.
That is if you closed the file. Since you haven't closed the file, the file is already open and you keep reopening it (which could be the cause of your problem)
Another thing is, how can
if (status == EOF) {
count = MAX_PLAYRS;
}
Give you the current count? Regardless of the count of the players in the file, you are just setting it to MAX_PLAYERS.
Another thing is that count is an input to the function that is not a pointer, so setting it does not change the value outside the function (which is what I assumed you wanted).
Here is how I would do it with minimum change to your code:
#include <stdio.h>
#define MAX_NAME 20
#define MAX_PLAYRS 16
typedef struct {
char pname[MAX_NAME];
int runs;
char how_out;
} Team_t;
Team_t player[MAX_PLAYRS];
Team_t *player_ptr[MAX_PLAYRS];
void get_names (int count, char *str, FILE *inp);
int main (void) {
FILE *inp;
int i;
int count;
inp = fopen("teamnames.rtf", "r");
for (i = 0; i < MAX_PLAYRS; i++) {
get_names(&count, player[i].pname, inp);
printf("Player: %s\n", player[i].pname);
}
}
void get_names (int *count, char *str) {
char status;
status = fscanf(inp, "%s", str);
if (status == EOF) {
*count = MAX_PLAYRS;
}
}
Here is how I would do it more concisely:
#include <stdio.h>
#define MAX_NAME 20
#define MAX_PLAYRS 16
typedef struct {
char pname[MAX_NAME];
int runs;
char how_out;
} Team_t;
Team_t player[MAX_PLAYRS];
Team_t *player_ptr[MAX_PLAYRS];
int get_names (Team_t *team);
int main (void) {
get_names(player);
}
int get_names (Team_t *team) {
int i = 0;
FILE *inp;
inp = fopen("teamnames.rtf", "r");
while (i < MAX_PLAYRS && !feof(inp) {
fscanf(inp, "%s", team[i].pname);
printf("Player: %s\n", player[i].pname);
}
}
Note that the problems with fscanf, checking array boundaries etc are not the concern of this solution, but this rather gives you the idea of what to do not a code for you to copy-paste.