About `argv` and opening a file with command line - c

I have this code:
#include <stdio.h>
int main ( int argc, char *argv[] )
{
FILE *file;
int x;
if ( argc != 2 )
printf( "Use: %s file name", argv[0] );
else {
if ((file=fopen( argv[1], "r" ))== 0 )
printf( “Couldn't open the file.\n" );
else {
while (( x = fgetc( file ) ) != EOF) printf( "%c", x );
fclose( file );
}
}
return 0;
}
Now, having this code, how do I execute a file from terminal (that is on the pic as well as my configuration of NetBeans). http://i.stack.imgur.com/6WRh3.png

First, better replace your statement (in your program above)
printf( “Couldn't open the file.\n" );
with
perror(argv[1]);
then, simply compile your program in your terminal, e.g. type there a shell command similar to
gcc -Wall -g mysource.c -o myprog
(Read more about invoking GCC: the -Wall option asks for nearly all warnings and is very useful -so never miss it-; you could even add -Wextra to get even more warnings; the -g is asking for DWARF debugging information in the ELF executable and enables you to use later gdb)
assuming your source code is in a file named mysource.c in the current working directory (use pwd command to query that current directory, ls -al to list it, and cd builtin command to change it)
at last, run your program as
./myprog sometestfile.txt
You might want to use the debugger. Read first about GDB, and try perhaps
gdb ./myprog
(I am guessing you are on Linux or some other POSIX compliant operating system, and using GCC compiler)
Read more about perror(3), command line interface, shells, globbing, glob(7), PATH variable
Later, you'll want to have some bigger program of yours made in several translation units, having some common header file (to be #included in all of them). Then you'll use a builder like GNU make. You could use a good editor like emacs, some version control like git, etc...
(you might realize that NetBeans is not very useful, because you can have even better developing comfort with your own collection of tools; having the freedom to choose your tools is worthwhile!)
PS. Perhaps replace printf( "%c", x ); with the shorter and more efficient putchar(x); ...

Related

GCC/Command Prompt error: '.' is not recognized as an internal or external command

I'm fairly new to C and am completely new to using the command prompt and GCC to compile and run my programs. I'm struggling to find the right words to ask this question properly so please bear with me, I am doing my best.
I need to use GCC to compile and run this C program but I'm getting an error that I do not understand. In this example program, I was told to use these lines to compile and run the code:
$ gcc -Wall -std=c99 -o anagrams anagrams.c
$ ./anagrams dictionary1.txt output1.txt
So that is what I did. GCC does compile the program file, so the first line does not give me any error. But GCC does not like the second line, as shown below:
C:\Users\...\Example>gcc -Wall -std=c99 -o anagrams anagrams.c
C:\Users\...\Example>./anagrams dictionary1.txt output1.txt
'.' is not recognized as an internal or external command,
operable program or batch file.
Everywhere I look, it says to use "./filename" to run the program after compiling so I don't understand why it is not working for me. Any help or advice would be really appreciated.
Also, here is the main() of the program to show why those two .txt files are needed:
int main(int argc, char *argv[])
{
AryElement *ary;
int aryLen;
if (argc != 3) {
printf("Wrong number of arguments to program.\n");
printf("Usage: ./anagrams infile outfile\n");
exit(EXIT_FAILURE);
}
char *inFile = argv[1];
char *outFile = argv[2];
ary = buildAnagramArray(inFile,&aryLen);
printAnagramArray(outFile,ary,aryLen);
freeAnagramArray(ary,aryLen);
return EXIT_SUCCESS;
}
'.' is not recognized as an internal or external command
This is not a GCC error. The error is issued by the shell when trying to run a command.
On Windows this
./anagrams dictionary1.txt output1.txt
should be
.\anagrams dictionary1.txt output1.txt
as on Windows the path delimiter is \ as opposedto IX'ish systems where it is /.
On both systems . denotes the current directory.
The reason for the crash you mention in your comment is not obvious from the minimal sources you show. Also this is a different question.

Is there a way of opening a directory from a specific path using stdio.h and stdlib.h?

I'm trying to make a program in C which gets a path of a directory and does things with the files inside.
Is there any way of doing this without using dirent.h or dir.h?
Also, is there any function which opens a directory with a url such as fopen but that opens files with a url path?
The C language does not have the notion of directories so there is no standard C way of using them.
The <dirent.h> thing is a POSIX API, so it should be available in any *nix OS. Other oses have other mechanisms to read the directory. For example, in Windows there is FindFirstFile()/FindNextFile().
You could use a third party, OS agnostic library, of course, but it will use any of these APIs under the hood.
On modern Unix-like systems, the answer is No (even though you can open a directory for reading, you can't actually read from it).
If you go back far enough in history, the answer was 'sometimes'. If you look at p183-4 of the second edition of K&R, you will see code reading a directory directly. That simply does not work on current versions of Unix.
You might be able to open a directory for reading, but you can't then do anything more with it.
$ cat opendot.c
#include <stdio.h>
int main(void)
{
FILE *fp = fopen(".", "r");
if (fp != 0)
{
printf("OK\n");
char buffer[256];
size_t nbytes;
if ((nbytes = fread(buffer, sizeof(char), sizeof(buffer), fp)) > 0)
{
for (size_t i = 0; i < nbytes; i++)
printf("0x%.2X\n", buffer[i]);
}
else
printf("Read failed\n");
fclose(fp);
}
else
printf("Failed\n");
return 0;
}
$ make opendot
gcc -O3 -g -std=c11 -Wall -Wextra -Werror opendot.c -o opendot
$ ./opendot
OK
Read failed
$
(Tested on Mac OS X 10.10.3 with GCC 5.1.0.)
You can use open() to open a directory for reading, primarily so you can use the file descriptor in operations such as fchdir() and
openat(). The fopen() calls illustrated above use the open() function underneath.
But you can't actually read from the directory.

C file not reading properly

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.

printf doesn't work, even with newline and fflush()

I'm compiling the below C code with gcc. No errors are thrown during compilation or at runtime. I ran through the code with gdb, and the answer given in sum is correct at the end, yet the printf() does not display anything on the screen. I've tried all sorts of combinations of fprintf(), printf(), and fflush(), but nothing works.
What do I need to change so the program will print the result to stdout?
#include <stdio.h>
#include <stdlib.h>
int main()
{
int num = 9;
int i, sum; i = 1, sum = 0;
while (i < 2 * num) {
sum = sum + i * i;
++i;
}
printf("sum: %d\n", sum);
fflush(stdout);
return 0;
}
The code is correct, and should print sum: 1785 for any conforming implementation.
This is a guess (update: which turns out to be correct), but ...
You've named the source file test.c, and you compile it with:
$ gcc test.c -o test
(or something similar) and execute it with:
$ test
which produces no output.
The problem is that test is a standard Unix command (and also a built-in command in some shells). When you type a command name to the shell, it first looks for built-in commands, then for executables in directories specified in your $PATH environment variable.
To execute a command in the current directory, prepend ./ to the name:
$ ./test
sum: 1785
$
This applies to any command in the current directory. There are so many built-in commands that you can't reasonably avoid colliding with them. Cultivating the habit of running executables in the current directory by typing ./whatever means that name collisions don't matter.
(Don't be tempted to add . to the front of your $PATH; that's dangerous. Think about what could happen if you cd into a directory and type ls, if there happens to be a malicious ls command there.)
There is nothing wrong with your program. It has to work. Try running it with redirection:
./a.out > myout
..and see if you get any output. If not, I'd suspect there is a problem with some kind of standard library mismatch.
Another option to check would be to build using SUN C compiler as opposed to gcc and see if that works. If it does, gcc is the culprit.

Calling execve bash on bash scripts can't find arguments

I have two (Ubuntu Linux) bash scripts which take input arguments. They need to be run simultaneously. I tried execve with arguments e.g.
char *argv[10] = { "/mnt/hgfs/F/working/script.sh", "file1", "file2", NULL };
execve(argv[0], argv, NULL)
but the bash script can't seem to find any arguments at e.g. $0, $1, $2.
printf "gcc -c ./%s.c -o ./%s.o\n" $1 $1;
gcc -c ./$1.c -o ./$1.o -g
exit 0;
output is gcc -c ./main.c -o ./main.o
and then a lot of errors like /usr/include/libio.h:53:21: error: stdarg.h: No such file or directory
What's missing?
Does your script start with the hashbang line? I think that's a must, something like:
#!/bin/bash
For example, see the following C program:
#include <stdio.h>
#include <unistd.h>
char *argv[10] = { "./qq.sh", "file1", NULL };
int main (void) {
int rc = execve (argv[0], argv, NULL);
printf ("rc = %d\n", rc);
return 0;
}
When this is compiled and run with the following qq.sh file, it outputs rc = -1:
echo $1
when you change the file to:
#!/bin/bash
echo $1
it outputs:
file1
as expected.
The other thing you need to watch out for is with using these VMWare shared folders, evidenced by /mnt/hgfs. If the file was created with a Windows-type editor, it may have the "DOS" line endings of carriage-return/line-feed - that may well be causing problems with the execution of the scripts.
You can check for this by running:
od -xcb /mnt/hgfs/F/working/script.sh
and seeing if any \r characters appear.
For example, if I use the shell script with the hashbang line in it (but appen a carriage return to the line), I also get the rc = -1 output, meaning it couldn't find the shell.
And, now, based on your edits, your script has no trouble interpreting the arguments at all. The fact that it outputs:
gcc -c ./main.c -o ./main.o
is proof positive of this since it's seeing $1 as main.
The problem you actually have is that the compiler is working but it cannot find strdarg.h included from your libio.h file - this has nothing to do with whether bash can see those arguments.
My suggestion is to try and compile it manually with that command and see if you get the same errors. If so, it's a problem with what you're trying to compile rather than a bash or exec issue.
If it does compile okay, it may be because of the destruction of the environment variables in your execve call.

Resources