I'm trying to use "echo FileName.txt | a.c" in terminal and read the data from the file into a array i got in a header file, but the code I have so far is just giving me a infinite loop. I tried storing the info in a local array also but still the same result.
main(int argc, char *argv[]) {
extern char test[];
FILE *fp;
int i = 0;
int c; // was char c; originally
if (argc == 1) {
fp = stdin;
} else {
fp = fopen (argv[1], "r");
}
while ((c = getc(fp)) != EOF) {
test[i] = c;
printf("%c", test[i]);
i++;
}
}
(1) Change variable c to an int so it recognizes EOF.
(2) Don't increment i before your printf or you will be printing junk.
Not sure what you are trying to accomplish with the echo thing.
NOTE: I'm assuming that your program is intended to do what the code in your question actually does, namely read input from a file named by a command-line argument, or from stdin if no command-line argument is given. That's a very common way for programs to operate, particularly on Unix-like systems. Your question and the way you invoke the program suggest that you're doing something quite different, namely reading a file name from standard input. That's an unusual thing to do. If that's really your intent, please update your question to clarify just what you're trying to do.
Given this assumption, the problem isn't in your program, it's in how you're invoking it. This:
echo FileName.txt | a.c
will feed the string FileName.txt as input to your program; the program has no idea (and should have no idea) that it's a file name.
The way to pass a file name to your program is:
a.c FileName.txt
Or, if you want to read the contents of the file from stdin:
a.c < FileName.txt
(In the latter case, the shell will take care of opening the file for you.)
You could read a file name from stdin, but it's rarely the right thing to do.
A few other points (some already pointed out in comments):
An executable file probably shouldn't have a name ending in .c; the .c suffix indicates a C source file.
You should declare main with an explicit return type; as of C99, the "implicit int" rule was removed, and it was never a particularly good idea anyway:
main(int argc, char *argv[]) { /* ... */ }
You're reading the entire contents of the input file into your test array. This is rarely necessary; in particular, if you're just copying an input file to stdout, you don't need to store more than one character at a time. If you do need to store the contents of a file in an array, you'll need to worry about not overflowing the array. You might want to abort the program with an error message if i exceeds the size of the array.
See also the rest of the advice in Jonathan Leffler's comment; it's all good advice (except that I think he misunderstood the purpose of your test array, which you're using to store the contents of the file, not its name).
Related
I'm trying to read from .txt file until I hit the character "=". Text file is always the same,contains only these strings:
TaskLimit=3
cc pr.c && ./a.out
Sometimes the code works fine and quits the while loop and sometimes it prints "TaskLimit" but then throws "Segmentation fault (core dumped)" error. Any ideas what am I doing wrong? Should I clear the buf[] or something?
char buf[1];
file = open(argv[1], O_RDONLY);
if (file == -1){
perror("Error opening file");
exit(1);
}
while(1){
read(file, buf, 1);
if(buf[0]=='=') {printf("I'm out");break;}
printf("%c",buf[0]);
//further actions
edit:
in the "further actions" I'm trying to convert a char to int and this seems to be the problem:
char limit_char[0];
int limit;
read(file,limit_char,1);
limit=atoi(limit_char[0]);
edit2:
changing this line
limit=atoi(limit_char[0]);
to
limit=atoi(&limit_char);
helped.
The most important part of C programming is checking return values.
In your sample code sample you do it for open(2), but not for read(2) and you should, because not only does it tell if there was an error, it also tells how many bytes have been read. Excerpt from the man page:
On success, the number of bytes read is returned (*zero indicates end of file*),
and the file position is advanced by this number.
That is, knowing that there is nothing more to read - return value of zero - can let you break from the loop in case the user gave you an invalid file.
When you learn C, I suggest (and pretty much every person on this site) to always compile with -Wall -Wextra -Werror. C is a spartan language and mastering it requires discipline. GCC (or whatever your compiler is) would never have let you execute:
limit=atoi(&limit_char);
As the type of &limit_char is effectively char ** and atoi expects a const char *.
atoi requires a NULL-terminated array of char so your array needs 1 more element than you're reading in.
char limit_char[2];
int limit;
read(file,limit_char,1);
limit_char[1]='\0';
limit=atoi(limit_char);
beyond that, you should probably be checking the return value from read to make sure you've actually read something in.
In your code, your refer to argv[1] for the filename, but on the example usage (cc pr.c && ./a.out) you don't specify any filename.
In you read() statement you use a variable plik which is not defined anywhere, use file here, i.e. the variable you used to store the result of `open().
Fix this and it will work.
This declaras an array of length zero which doesn't make much sense. BTW: normally the compiler should emit at least a warning.
char limit_char[0];
this wont work, you need an array of length 1 because you read 1 byte with read:
char limit_char[1];
or rather this:
char limit_char;
...
read(file, &limit_char, 1);
I have been trying for a long time to figure out how to get the program to read text from a file. I have tried a solution with fgets() and a loop. The program runs but does not print the variable, indicating the text was not extracted.
#include <stdio.h>
#include <string.h>
#include "stdfn.h"
int main(int argc, char* argv[])
{
char* request;
char bf_text[1024];
char character;
intro("Site Blocker", 2014, "MIT");
request = bash("curl http://redsec.ru/blocked_sites.txt"); // Source of bash() is at line 139 https://github.com/Pavelovich/lib-c/blob/master/stdfn.h
//printf("%s", request);
FILE* block_file = fopen(".blocked_sites", "w+"); // Changed from "w" based on this thread, currently only outputs a small part of the file.
FILE* hosts = fopen("hosts", "w");
FILE* hosts_tmp = fopen(".hosts", "w");
// Print the text of the web request to the temporary
// .blocked_sites file
fprintf(block_file, "%s", request);
rewind(block_file);
fread(bf_text, sizeof(block_file), 1, block_file);
printf("%s", bf_text);
fclose(block_file);
return 0;
}
sizeof(block_file) does not give you the size of the file. It'll give you the size of a file pointer, probably either four or eight bytes. Probably eight in your case, since you're saying it's reading "74.125.2", which is eight bytes, and then going haywire. You'll need to use something like stat() on a POSIX system, or a combination of fseek() and ftell().
You should also open files in binary mode if you're going to use fread() or fwrite(), since they are binary file IO functions. It won't make a difference on UNIX systems, but it may well on Windows, for instance. You shouldn't really mix text and binary mode IO functions in the way that you have for this reason.
You should also be checking the returns from your fopen() calls to make sure they succeeded.
And that bash() function you're using is completely broken, too. You'll get a memory leak every time it's called because it never free()s output, and it's making the same sizeof error that you are, although it'll still work because of the loop it's in. It'll just waste all that memory it allocated. And you are leaking memory because you never free(request). And you'd better never #include it in more than one translation unit, either, unless you want multiple definition errors all over the place. That whole "library" is riddled with schoolboy-type errors, in fact, including repeated failures to check the return from malloc(), allocating memory to fit a pointer instead of the thing it's pointing at, and so on.
You are opening block_file for "write only". Try changing the mode parameter to "w+" i.e.
FILE block_file = fopen(".blocked_sites", "w+");
If you want to open an existing file rather than creating a new one each time, use "r+" or "a+" instead of "w+".
Making a program that adds user records to text file; so far so good! Yet I ran into a problem that I can not figure out on my own.
int main()
{
FILE *fp;
struct info
{
char name[15];
char surename[15];
char gender[15];
char education[15];
} info;
char c;
int i,j,a;
struct info sem;
beginning:
scanf("%d",&a);
if (a==1)
and at this part if user chooses option one 1, program needs to check all the records per person in txt file and printf me every single person information who has bachelors education.
{
FILE *fp=fopen("info.txt", "r");
char tmp[256]={0x0};
while(fp!=NULL && fgets(tmp, sizeof(tmp),fp)!=NULL)
{
if(strstr(tmp,"bachelors"))
printf("test test");
fprintf(fp, "\n%s %s %s %s %s %s",
sem.name,
sem.surname,
sem.gender,
sem.education,);
}
if(fp!=NULL) fclose(fp);
goto beginning;
}
This code so far detects the word "bachelor" but doesn't want to print out the line where it detected it; any ideas how to solve it? Plus, any suggestions how to make sure program only checks education field and doesn't give me false positive if some one would be named Bachelors?
printf/fprintf procedures use internal buffers to avoid calling the syscall "write" everytime.
I would say that you should add a '\n' character at the end of your string to actually force flushing the buffers writing the test. Moreover your token "bachelors" has to be in the 256 first characters of your file.
Second question depends on how your file is formatted, and you are the only one who knows that.
What output do you actually get? You say it doesn't want to print out the correct lines, but does that mean it prints all lines, no lines, some but not others?
Looking at your program, I would hazard a guess that every line is being printed out. You need braces around if(strstr(tmp,"bachelors")) if you want more than one statement in the body of the if.
EDIT:
In addition to your braces problem, you are attempting to use fprintf to print back to fp, which was opened in read mode (using the r flag). You need to use read/update mode (r+) if you want to modify info.txt. However, this is probably not the way you want to do this.
Firstly, you stated you wanted to "printf" the data, which means printing to standard out. If so then you should use printf instead of fprintf. On the other hand it would seem likely that what you want to do is to read lines from one text file and print data out to another file. In that case you probably want two files.
Even with the above modifications, you will be printing the same data to file each time, since the sem struct is not being updated at all.
Finally, your fprintf format string expects six inputs and you only have four (and an erroneous trailing ,). Why?
I'm trying to read in a text file line by line and process each character individually.
For example, one line in my text file might look like this:
ABC XXXX XXXXXXXX ABC
There will always be a different amount of spaces in the line. But the same number of characters (including spaces).
This is what I have so far...
char currentLine[100];
fgets(currentLine, 22, inputFile);
I'm then trying to iterate through the currentLine Array and work with each character...
for (j = 0; j<22; j++) {
if (¤tLine[j] == 'x') {
// character is an x... do something
}
}
Can anyone help me with how I should be doing this?
As you can probably tell - I've just started using C.
Something like the following is the canonical way to process a file character by character:
#include <stdio.h>
int main(int argc, char **argv)
{
FILE *fp;
int c;
if (argc != 2) {
fprintf(stderr, "Usage: %s file.txt\n", argv[0]);
exit(1);
}
if (!(fp = fopen(argv[1], "rt"))) {
perror(argv[1]);
exit(1);
}
while ((c = fgetc(fp)) != EOF) {
// now do something with each character, c.
}
fclose(fp);
return 0;
}
Note that c is declared int, not char because EOF has a value that is distinct from all characters that can be stored in a char.
For more complex parsing, then reading the file a line at a time is generally the right approach. You will, however, want to be much more defensive against input data that is not formatted correctly. Essentially, write the code to assume that the outside world is hostile. Never assume that the file is intact, even if it is a file that you just wrote.
For example, you are using a 100 character buffer to read lines, but limiting the amount read to 22 characters (probably because you know that 22 is the "correct" line length). The extra buffer space is fine, but you should allow for the possibility that the file might contain a line that is the wrong length. Even if that is an error, you have to decide how to handle that error and either resynchronize your process or abandon it.
Edit: I've added some skeleton of an assumed rest of the program for the canonical simple case. There are couple of things to point out there for new users of C. First, I've assumed a simple command line interface to get the name of the file to process, and verified using argc that an argument is really present. If not, I print a brief usage message taking advantage of the content of argv[0] which by convention names the current program in some useful way, and exit with a non-zero status.
I open the file for reading in text mode. The distinction between text and binary modes is unimportant on Unix platforms, but can be important on others, especially Windows. Since the discussion is of processing the file a character at a time, I'm assuming that the file is text and not binary. If fopen() fails, then it returns NULL and sets the global variable errno to a descriptive code for why it failed. The call to perror() translates errno to something human-readable and prints it along with a provided string. Here I've provided the name of the file we attempted to open. The result will look something like "foo.txt: no such file". We also exit with non-zero status in this case. I haven't bothered, but it is often sensible to exit with distinct non-zero status codes for distinct reasons, which can help shell scripts make better sense of errors.
Finally, I close the file. In principle, I should also test the fclose() for failure. For a process that just reads a file, most error conditions will already have been detected as some kind of content error, and there will be no useful status added at the close. For file writing, however, you might not discover certain I/O errors until the call to fclose(). When writing a file it is good practice to check return codes and expect to handle I/O errors at any call that touches the file.
You don't need the address operator (&). You're trying to compare the value of the variable currentLine[j] to 'x', not it's address.
ABC XXXX XXXXXXXX ABC has 21 characters. There's also the line break (22 chars) and the terminating null byte (23 chars).
You need to fgets(currentLine, 23, inputFile); to read the full line.
But you declared currentLine as an array of 100. Why not use all of it?
fgets(currentLine, sizeof currentLine, inputFile);
When using all of it, it doesn't mean that the system will put more than a line each time fgets is called. fgets always stops after reading a '\n'.
Try
while( fgets(currentLine, 100, inputFile) ) {
for (j = 0; j<22; j++) {
if (/*&*/currentLine[j] == 'x') { /* <--- without & */
// character is an x... do something
}
}
}
Does a quine print the ACTUAL code of the program i.e not obfuscated or does it print the obfuscated program?
I don't think obfuscation has anything to do with it. Usually a quine prints the actual source code of the program itself.
Suppose that you had a C program which prints an "obfuscated" or otherwise cosmetically modified version of its source. For example, suppose there's a difference in whitespace or variable names.
Then that program would not be a quine, since by definition a quine is a program which prints itself, and by "itself" we mean the exact same sequence of bytes. But the output of that program, once compiled, would print the same thing as the original program (since it's just a cosmetic variant), i.e. itself. So the output is a quine.
This sometimes eases the process of writing a quine - just write a "nearly-quine", which maybe doesn't get the formatting exactly right, run it once, and the output is your actual quine.
This is all assuming a quine in C. A quine in x86 machine code would have to output not its C source, but the same sequence of bytes that makes up the .exe file.
I'm not sure what you mean by "ACTUAL code" as opposed to "obfuscated code", but to test whether something is a quine or not, you have to decide what language it's supposed to be a quine in. Maybe by deciding that you can answer your own question - do you just want a quine in C, or a quine that has something to do with your obfuscator?
Here is an actual quine in standard C, found at Wikipedia:
main() { char *s="main() { char *s=%c%s%c; printf(s,34,s,34); }"; printf(s,34,s,34); }
You will notice that its structure is relatively straightforward. It uses a string constant containing the text of the program as both the format string and one of the values to be formatted by printf().
When compiled and run, it prints exactly that single line of code.
There are examples of quines in a variety of languages, including several more in C, at the wiki article.
Following is a simple quine code. This source code need to saved as "quine_file.c". Compile and execute.
Here a simple file pointer is taken and it is used to read the source file line by line and print it to the stdout.
#include <stdio.h>
#include <stdlib.h>
void main()
{
FILE *fp = NULL;
char * line = NULL;
int len = 0;
int read;
fp = fopen("quine_file.c","r");
if(fp == NULL)
return;
while ((read = getline(&line, &len, fp)) != -1)
{
printf("%s", line);
}
fclose(fp);
if (line)
free(line);
exit(EXIT_SUCCESS);
}
A quine is a program which prints its own listing. This means that when the program is run, it must print out precisely those instructions which the programmer wrote as part of the program (including, of course, the instructions that do the printing, and the data used in the printing).
- David Madore
Further reading
JavaScript example
$=_=>`$=${$};$()`;$();
when executed this program will display the following string
"$=_=>`$=${$};$()`;$();"
Featured in the art of code video # 30m21s
- Dylan Beattie
#include <stdio.h>
main(){
FILE* fp = fopen("printItself.c", "r");
int c;
while ((c = getc(fp)) != EOF) putc(c, stdout);
}
Save it in a file named as printItself.c ... Problem with previous example is that if i add a line in program e.g int x; i will have to add it in the string also while taking care of newline and spaces etc ... but in this example you can add whatever you want.