What i would like to do:
Read bits from one file (input file), and write these (with some probability) inverted bits to other file (output file).
What is the problem:
Probability idea seem not to be working properly. And more importantly, output file always contains more characters then the original input file, while they should contain equal number of characters.
In this code sample, instead of inverted bits i have put 'x' and 'y', so that it is more obvious that output file contains more characters
INPUT file: 01001
OUTPUT file: xyxxxyx
The code:
void invert_bits(FILE **input, FILE **output, double prob){
srand(clock());
char symbol;
while((symbol = getc(*input)) != EOF){
double result = rand()/RAND_MAX;
if(result < prob){
if(simbol == '0'){
char bit = 'x';
fprintf(*output, &bit);
}
else{
char bit = 'y';
fprintf(*output, &bit);
}
}else{
fprintf(*output, &symbol);
}
}
}
(f)printf expects a format string as its second argument. You are providing it with the address of a char, which is not even a valid string (since it is not NUL-terminated).
Don't do that. It's a bad habit. When you use printf, fprintf or sprintf always use a format string. (Read this for more information.)
You could have used fprintf(*output, "%c", bit); but it would be a lot simpler to just print the character with fputc(bit, *output);
I don't understand why you feel the need to pass the FILE* arguments as pointers, by the way.
You aren't using the fprintf function properly.
The function's signature is:
int fprintf ( FILE * stream, const char * format, ... );
Instead of a null terminated string, you're providing it with an address of a char, which might follow by a null character, or might not.
The correct way of printing a character with the *printf functions is:
fprintf(*output, "%c", bit);
P.S. Why are you receiving a pointer to the file handle, i.e. FILE** and not just FILE*?
Related
I have tried this code to separate my Str[] string into 2 string, but my problem is "I want to separate John(name) as string and 100(marks) as integer",How can I do it, any suggestion?
#include <stdio.h>
#include <string.h>
void main()
{
char Str[] = "John,100";
int i, j, xchange;
char name[50];
char marks[10];
j = 0; xchange = 0;
for(i=0; Str[i]!='\0'; i++){
if(Str[i]!=',' && xchange!=-1){
name[i] = Str[i];
}else{
xchange = -1;
}
if(xchange==-1){
marks[j++] = Str[i+1];
}
}
printf("Student name is %s\n", name);
printf("Student marks is %s", marks);
}
How to separate "John,100" into 2 strings?
There are three common approaches:
Use strtok() to split the string into individual tokens. This will modify the original string, but is quite simple to implement:
int main(void)
{
char line[] = "John,100;passed";
char *name, *score, *status;
/* Detach the initial part of the line,
up to the first comma, and set name
to point to that part. */
name = strtok(line, ",");
/* Detach the next part of the line,
up to the next comma or semicolon,
setting score to point to that part. */
score = strtok(NULL, ",;");
/* Detach the final part of the line,
setting status to point to it. */
status = strtok(NULL, "");
Note that if you change char line[] = "John,100"; then status will be NULL, but the code is otherwise safe to run.
So, in practice, if you required all three fields to exist in line, it would be sufficient to ensure the last one was not NULL:
if (!status) {
fprintf(stderr, "line[] did not have three fields!\n");
return EXIT_FAILURE;
}
Use sscanf() to convert the string. For example,
char line[] = "John,100";
char name[20];
int score;
if (sscanf(line, "%19[^,],%d", name, &score) != 2) {
fprintf(stderr, "Cannot parse line[] correctly.\n");
return EXIT_FAILURE;
}
Here, the 19 refers to the number of chars in name (one is always reserved for the end-of-string nul char, '\0'), and [^,] is a string conversion, consuming everything except a comma. %d converts an int. The return value is the number of successful conversions.
This approach does not modify the original string, and it allows you to try a number of different parsing patterns; as long as you try them the most complex one first, you can allow multiple input formats with very little added code. I do this regularly when taking 2D or 3D vectors as inputs.
The downside is that sscanf() (all functions in the scanf family) ignores overflow. For example, on 32-bit architectures, the largest int is 2147483647, but scanf functions will happily convert e.g. 9999999999 to 1410065407 (or some other value!) without returning an error. You can only assume the numerical inputs are sane and within the limits; you cannot verify.
Use helper functions to tokenise and/or parse the string.
Typically, the helper functions are something like
char *parse_string(char *source, char **to);
char *parse_long(char *source, long *to);
where source is a pointer to the next character in the string to be parsed, and to is a pointer to where the parsed value will be stored; or
char *next_string(char **source);
long next_long(char **source);
where source is a pointer to a pointer to the next character in the string to be parsed, and the return value is the value of the extracted token.
These tend to be longer than above, and if written by me, then quite paranoid about the inputs they accept. (I want my programs to complain if their input cannot be reliably parsed, rather than silently produce garbage.)
If the data is some variant of CSV (comma-separated values) read from a file, then the proper approach is a different one: instead of reading the file line by line, you read the file token by token.
The only "trick" is to remember the separator character that ended the token (you can use ungetc() for this), and use a different function to (read and ignore the rest of the tokens in the current record, and) consume the newline separator.
I am familiar with the sizeof operation in C, but when I use it for the string "1234abcd" it only returns 4, which I am assuming is accounting for the last 4 characters.
So how would I get this to be a string of size 8?
specific code is as follows:
FILE *in_file;
in_file = fopen(filename, "r");
if (in_file == NULL) {
printf("File does not exist\n");
return 1;
}
int val_to_inspect = 0;
fscanf(in_file, "%x", &val_to_inspect);
while (val_to_inspect != 0) {
printf("%x", val_to_inspect);
int length = sizeof val_to_inspect;
printf("%d", length);
Again, the string that is being read from the file is "1234abcd", just to clarify.
There're a couple of issues here:
sizeof operator returns the size of the object. In this case it returns the size of val_to_inspect, which is an int.
http://en.cppreference.com/w/cpp/language/sizeof
fscanf reads from a stream and interprets it. You are only scanning an integer ("%x"), not a string.
http://en.cppreference.com/w/cpp/io/c/fscanf
Lastly, if you actually had a nil-terminated string, to get its length you could use strlen().
TL;DR, to get the length of a string, you need to use strlen().
That said, be a little cautious while using sizeof, it operates on the data type. So, if you pass a pointer to it, it will return you the size of the pointer variable, not the length of the string it points to.
In several important ways, only some of which have anything to do with sizeof, you are mistaken about what your code actually does.
FILE *in_file;
in_file = fopen(filename, "r");
if (in_file == NULL)
{
printf("File does not exist\n");
return 1;
}
Kudos for actually checking whether fopen succeeded; lots of people forget to do that when they are starting out in C. However, there are many reasons why fopen might fail; the file not existing is just one of them. Whenever an I/O operation fails, make sure to print strerror(errno) so you know the actual reason. Also, error messages should be sent to stderr, not stdout, and should include the name of the affected file(s) if any. Corrected code looks like
if (in_file == NULL)
{
fprintf(stderr, "Error opening %s: %s\n", filename, strerror(errno));
return 1;
}
(You will need to add includes of string.h and errno.h to the top of the file if they aren't already there.)
int val_to_inspect = 0;
fscanf(in_file,"%x", &val_to_inspect);
This code does not read a string from the file. It skips any leading whitespace and then reads a sequence of hexadecimal digits from the file, stopping as soon as it encounters a non-digit, and immediately converts them to a machine number which is stored in val_to_expect. With the file containing 1234abcd, it will indeed read eight characters from the file, but with other file contents it might read more or fewer.
(Technically, with the %x conversion specifier you should be using an unsigned int, but most implementations will let you get away with using a signed int.)
(When you get more practice in C you will learn that scanf is broken-as-specified and also very difficult to use robustly, but for right now don't worry about that.)
while (val_to_inspect != 0) {
printf("%x", val_to_inspect);
int length = sizeof val_to_inspect;
printf("%d", length);
}
You are not applying sizeof to a string, you are applying it to an int. The size of an int, on your computer, is 4 chars, and that is true no matter what the value is.
Moreover, sizeof applied to an actual C string (that is, a char * variable pointing to a NUL-terminated sequence of characters) does not compute the length of the string. It will instead tell you the size of the pointer to the string, which will be a constant (usually either 4 or 8, depending on the computer) independent of the length of the string. To compute the length of a string, use the library function strlen (declared in string.h).
You will sometimes see clever code apply sizeof to a string literal, which does return a number related to (but not equal to!) its length. Exercise for you: figure out what that number is, and why sizeof does this for string literals but not for strings in general. (Hint: sizeof s will return a number related to s's string length when s was declared as char s[] = "string";, but not when it was declared as char *s = "string";.)
As a final note, it doesn't matter in the grand scheme of things whether you like your opening braces on their own lines or not, but pick one style and stick to it throughout the entire file. Don't put some if opening braces on their own lines and others at the end of the if line.
It's better to create own counter to find the length of "1234abcd" by reading the character by character.
FILE *in_file;
char ch;
int length=0;
in_file = fopen("filename.txt", "r");
if (in_file == NULL)
{
printf("File does not exist\n");
return 1;
}
while (1) {
ch = fgetc(in_file);
printf("%c", ch);
if (ch == EOF)
break;
length++;
}
fclose(in_file);
printf ("\n%d",length);
Everyone, thank you for all the feedback. I realize I made a lot of mistakes with the original post, but im just switching to c from c++, so a lot of the things I'm used to cant really be applied the same way. This is all tremendously helpful, it's good to have a place to go to.
Len=sizeof(your string)/sizeof(char)-1
-1 is eof character null
If you want to get length of any from specific begining index just do Len-index
I am having problems reading strings with sscanf. I have dumbed down the code to focus on the problem. Below is a function in the whole code that is supposed to open a file and read something. But sscanf is acting strangely. For instance I declare a string called atm with the content 'ATOM'. Before the sscanf it prints this string as ATOM while after it is null. What could be the problem? I assume it must be an allocation problem but I could not find it. I tried some suggestions on other topics like replacing %s with other things but it did not help.
void Get (struct protein p, int mode, int type)
{
FILE *fd; //input file
char name[100]="1CMA"; //array for input file name
char string[600]; //the array where each line of the data file is stored when reading
char atm[100]="ATOM";
char begin[4];
int index1 =0;
fd = fopen(name, "r"); // open the input file
if(fd==NULL) {
printf("Error: can't open file.\n");
return 1;
}
if( type==0 ) { //pdb file type
if( mode==0 ) {
while( fgets(string, 600, fd)!=NULL ) {
printf("1 %s\n",atm);
sscanf (string, "%4s", begin );
printf("2 %s \n",atm);
}
}
}
fclose(fd);
free(fd);
free(name);
}
The string begin isn't big enough to hold the four characters that sscanf will read and its \0 terminator. If the \0 is written into atm (depending on where the strings are in memory), atm would be modified. From the sscanf manpage, about the s directive:
s Matches a sequence of non-white-space characters; the next pointer must be a pointer to character array that is long enough to hold the input sequence and the terminating null byte ('\0'), which is added automatically. The input string stops at white space or at the maximum field width, whichever occurs first.
I was able to reproduce this behavior on my machine, though the exact positioning of the strings in memory was a bit different. By printing the addresses of the strings, though, it is easy to figure exactly what's happening. Here's a minimal example:
#include<stdio.h>
int main() {
char begin[2];
char atm[100]="ATOM";
printf("begin: %p\n", begin);
printf("begin+16: %p\n", begin+16);
printf("atom: %p\n", atm);
printf("1 %s\n",atm);
sscanf("AAAABBBBCCCCDDDD", "%16s", begin);
printf("2 %s \n",atm);
return 0;
}
This produces the output:
$ ./a.out
begin: 0x7fffffffe120
begin+16: 0x7fffffffe130
atom: 0x7fffffffe130
1 ATOM
2
I printed the values of the pointers to figure out how big a string it would take to overflow into atm. Since (on my machine) atom begins at begin+16, reading sixteen characters into begin puts a null terminator at begin+16, which is the first character of atm, so now atm has length 0.
I have a file with integers. I want to write in a buffer those integers as chars (its ascii number). Because it is part of a bigger project please do not post different but please help me on that. What I especially need is chars to be stored in a buffer of type char *.
These are my declarations.
FILE *in;
long io_len = 1000;
char * buffer;
in=fopen("input.txt","a+");
buffer = malloc(io_len * sizeof(*buffer));
if(buffer == NULL){
perror("malloc");
exit(EXIT_FAILURE);
}
I am figuring out 2 sollutions.
If I write this one:
read_ret = read(in, buffer, io_len);
it reads from file in, io_len bytes and stores them in buffer. But it reads characters. So for example if I write 123 it will write to buffer 1,2,3 not the character with ascii number 123.
So I did this:
while((fscanf(in,"%d", &i))==1){
printf(": %d\n", i);
}
which reads the integers as I want. Now I am a little bit confused on how I will store them in buffer, as characters. I have tried this but it get me a segmentation fault.
while((fscanf(in,"%d", &i))==1){
printf(": %d\n", i);
buffer=(char) i;
printf("Character in Buffer:%s\n",buffer);
buffer++;
}
Have in mind that later in my file I am writing my buffer somewhere else, so whatever I will do I want the pointer to be at the start of my char array(if it makes sense what I am saying)
Your final code should at least give you a warning about assigning an integer to a pointer in the line buffer=(char) i;. It looks like you want to dereference the pointer.
You are also printing a string when it looks like you really only want to print a character at a time.
Your code should probably look like this:
int character_index = 0;
while((fscanf(in,"%d", &i))==1){
printf(": %d\n", i);
buffer[character_index]=(char) i;
printf("Character in Buffer:%c\n",buffer[character_index]);
character_index++;
}
I'm writing a version of the Unix expand utility that replaces tabs with spaces in a file. To do this, I'm reading in each character and testing if it is a tab character. If it is, it replaces the tab with the given amount of spaces, otherwise the character gets printed.
My main method goes like
int main(int argc, char *argv[]){
FILE *fp;
char *help1="-help";
char *help2= "--help";
//int spaces; //number of spaces to replace tabs
fp= fopen(argv[1], "rw");
parse_file(fp, 4);
fclose(fp);
return 0;
}
the parse_file method goes like
void parse_file(FILE *fp, int spaces)
{
int i; //loop counter
char c; //current character
while (c!= EOF)
{
c= getchar(); //get char from stream
if (c=='\t') //if char is a tab
{
for (i=0; i< spaces; i++)
putchar(" "); //replace with spaces
}
else
putchar(c); //otherwise, print the character
}
}
When compiling, I get an integer from pointer without cast warning for putchar(" "); and the program hits a segfault when executing.
So, my questions:
1- What is the warning "makes integer from pointer without cast" all about? What can I do to resolve it?
2- The code generates a segfault on execution with a text file passed in as an argument. Is there anything in this code that would cause that?
you must use
putchar(' ')
instead
putchar(" ")
You're calling putchar on a string (" "), but it wants a char argument (' '). (Actually an int, but only passing a char is safe.)
The segfault is probably due to the fclose on fp, which may be NULL. You should check the return value from fopen. The reason you only notice after parse_file is that it doesn't touch fp at all (it reads from stdin and writes to stdout). To use the stream fp, you should use getc(fp) and putc(fp) instead. (That still won't work because you'd overwrite the stream with more data than you're reading from it, so you'll get garbage out.)
In fact, the program is sure to segfault when no command line argument is given. Either fopen segfaults because it is handed the null pointer argv[1], or it returns a null pointer itself.
When writing these kinds of programs, please adhere to the Unix philosophy and write them as filters: read from stdin, write to stdout. Don't modify a file in-place if you don't have to.
In C string literals are of type char *, a pointer to some area containing string characters.
" " is a string literal, not a character. Use ' ' when you need a single character
As everyone else says, re. The use of char vs. string. As for the logic behind the actual error message you see, the string is a pointer to a const array of characters. Hence the error is saying it is converting the pointer to an int. Most of the char functions work with ints.
To summarise the issues (I'm repeating stuff other people have said, but issues 5 and 6 havehas not been mentioned so far):
putchar() does not take a string pointer as an argument but an int - the constant ' ' is an acceptable parameter
you don't check that argc > 1 before using argv[1]
you don't check that fopen() successfully opens the file
c should be defined as an int since in some character sets (char) -1 (0xFF) is a legitimate character and also the comparison c == EOF may fail if c is not sign extended
The first time through the loop c is used uninitialised and in the loop you also treat EOF as a normal character. The normal idiom in C programs is
int c;
while ((c = fgetc(fp)) != EOF)
{
// do stuff with c
}
You are getting your characters from stdin and not fp hence use fgetc() not getchar()
I think that covers everything.
To answer your explicit question, you get the warning "makes integer from pointer without cast" when an int is expected but you use a pointer (in this case the type of " " is const char*).
In addition to what has already been said, getchar() returns int not char. EOF is an int constant. You will need to read the result from getchar() into an int, check for EOF, and if not found, cast the int into a char.