As the title states, I am receiving an error when I try to build my project which states: In function 'print_usage': error: expected ')' before 'PROGRAM'
I am not exactly sure what is causing this error and was hoping someone could point me in the right direction.
#include <stdio.h>
#include <stdlib.h>
#include "lexer.h"
void print_usage();
void load_file(char *filename, char **buffer, size_t *size);
int main(int argc, char *argv[]) {
argc--;
argv++;
if(argc <= 0) {
print_usage();
exit(EXIT_FAILURE);
}
while(argc > 0) {
size_t size; /* I'm not using this, but it could be useful. */
Token token;
char *buffer = NULL;
unsigned int token_cnt = 0;
load_file(*argv, &buffer, &size);
if(buffer) {
char *b; /* editable copy of the buffer pointer */
b = buffer;
while(get_token(&b, &token) != TOKEN_EOF) {
printf("%s: ", id_string[token.id]);
if(token.str) {
printf("\"%s\"\n", token.str);
free(token.str);
}
else {
printf("no string found\n");
}
if(token.id != TOKEN_BAD) {
token_cnt++;
}
}
printf("\n----------------------\n");
printf("%u valid tokens found\n", token_cnt);
printf("----------------------\n");
free(buffer);
}
argc--;
argv++;
}
exit(EXIT_SUCCESS);
}
void print_usage() {
fprintf(stderr, "Usage: " PROGRAM " [file]...\n");
return;
}
argc--;
argv++;
/* Since you just incremented argv, you just lost the program name! */
/* You need argv[0] as the program name to create the error message */
if(argc <= 0) {
print_usage( argv[0] );
exit(EXIT_FAILURE);
}
void print_usage(char* program) {
fprintf(stderr, "Usage: %s [file]...\n", program);
}
Look up the syntax for fprintf(), you probably need something more like
void print_usage() {
fprintf(stderr, "Usage: %s [file]...\n", PROGRAM);
return;
}
Assuming PROGRAM is defined as a string somewhere.
Related
Ive been trying various ways to get my program to work. regardless of weather i try argv1 or argv2 first, the second one will segmentation fault. even if i try to print SOURCE2DEFINE or argv[2] AFTER a move() it will segmentation fault. i cannot move both files trying to run move twice will result in a segmentation fault. im assuming that it has to be something to do with pointers and allocation.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#define SOURCEDEFINE argv[1]
#define SOURCE2DEFINE argv[2]
#define DESTDEFINE argv[argc - 1]
#define ARGCDEFINE argc
#define COMMANDDEFINE argv[0]
int getIndex(char, char*);
char* fileGetName(char*);
void move(char*, char*);
void copy(char*, char*);
int main(int argc, char** argv)
{
printf("Test Argc: %d\n", argc);
int lengthArray = argc-2;
printf("Test Length: %d\n", lengthArray);
printf(" command %s\n", COMMANDDEFINE);
printf("%s\n", DESTDEFINE);
if(strcmp("./copy", COMMANDDEFINE) == 0)
{
// copy(source, dest);
}
else if(strcmp("./move", COMMANDDEFINE) == 0)
{
int i = 1;
printf("Test 1: %s\n", argv[i]);
printf("Test 2: %s\n", argv[argc-1]);
move(SOURCEDEFINE, DESTDEFINE);
printf("%s Filename debug \n", SOURCE2DEFINE);
move(SOURCE2DEFINE, DESTDEFINE);
// i++;
}
return 0;
}
void moveMultiple(int argc, char** argv){
int index = 1;
while(argv[index] != NULL){
if(index < argc - 1){
move(argv[index],argv[argc - 1]);
index++;
}
}
}
void move(char *source, char* dest)
{
printf("Running Move\n");
// FILE *s = fopen(source, "r");
// FILE *s;
//FILE *s = fopen(source, "r");
strcat(dest, fileGetName(source));
int l = link(source, dest);
//if(s == NULL)
if(l)
{
printf("Error, File Not Found");
perror("Link");
fflush(stdout);
exit(1);
}
remove(source);
}
void copy(char *source, char* dest)
{
printf("Running Copy\n");
strcat(dest, fileGetName(source));
int l = link(source, dest);
//if(s == NULL)
if(l)
{
printf("Error, File Not Found");
perror("Link");
fflush(stdout);
exit(1);
}
}
char* fileGetName(char *filename)
{
int i = 0;
int length = strlen(filename);
char *catString;
int index = getIndex('/', filename);
index--;
memcpy(catString,&filename[index], length);
return catString;
}
int getIndex(char i, char *s)
{
printf("Running getIndex\n");
int index = -1;
for(int l =0; l<strlen(s); l++){
if(s[l] == i) {
index = l;
}
}
return index;
}
Your move method changes dest (which is really argv[i]), and overwrites the memory after it: strcat(dest, fileGetName(source));. This destroys the other parameter and probably some other things. Don't write strings into memory you don't own.
So I'm working on a C program with UNIX as its terminal, and the program is supposed to call my directory recursively. The output should give me the directory themselves and the time period they were modified.
The code works, it compiles well, but it refuses to display its output.
And right now all I need is to display the output. But this is what it gives me...
I've tried ./compdir, ./compdir dir1 dir2, and also ./compdir dir2 dir1...the only possible solution in the UNIX terminal, but to no avail.
Can someone help me out? Here is the code down below. I appreciate your help.
#include <stdio.h>
#include <ctype.h>
#include <math.h>
#include <stdlib.h>
#include <dirent.h>
#include <errno.h>
#include <sys/stat.h>
#include <string.h>
#include <time.h>
#define E_INVALIDSWITCH 100
#define E_TOOMANYPARAMS 101
#define E_TOOFEWPARAMS 102
#define E_OPENDIRFAIL 103
void status();
void greetDirectory(char * baseDir, char * modDir);
int main(int argc, char ** argv)
{
int R_switch = 0;
char * modDir = NULL;
char * baseDir = NULL;
int i;
for (i = 1; i < argc; i++)
{
if (argv[i][0] == '-')
{
if (strcmp(argv[i], "-R") == 0)
{
R_switch = 1;
}
else
{
fprintf(stderr, "Error: Invalid switch %s\n", argv[i]);
status();
return E_INVALIDSWITCH;
}
}
else
{
if (baseDir == NULL)
{
baseDir = argv[i];
}
else if (modDir == NULL)
{
modDir = argv[i];
}
else
{
fprintf(stderr, "Error: Too many parameters\n");
status();
return E_TOOMANYPARAMS;
}
}
}
if (modDir == NULL)
{
fprintf(stderr, "Error: Too few parameters\n");
status();
return E_TOOFEWPARAMS;
}
if (R_switch)
{
greetDirectory(baseDir, modDir);
}
return 0;
}
void status()
{
printf("\t-R\tGreet all files in current directory\n");
printf("\t<modDir>\tName of person being greeted\n");
}
char *formatdate(char *buff, time_t val)
{
strftime(buff,200, "%d.%m.%Y %H:%M:%S", localtime(&val));
return buff;
}
void greetDirectory(char * baseDir, char * modDir)
{
DIR * directory;
struct dirent * dirInfo;
directory = opendir(baseDir);
if (directory == NULL)
{
fprintf(stderr,
"opendir() failed for '%s', errno=%d\n",
baseDir,
errno);
exit(E_OPENDIRFAIL);
}
while((dirInfo = readdir(directory)) != NULL)
{
if (strcmp(dirInfo->d_name, ".") != 0 &&
strcmp(dirInfo->d_name, "..") != 0)
{
/* BASE DIR*/
char basePathName[PATH_MAX];
strcpy(basePathName, baseDir);
strcat(basePathName, "/");
strcat(basePathName, dirInfo->d_name);
/* MOD DIR */
char modPathName[PATH_MAX];
strcpy(modPathName, modDir);
strcat(modPathName, "/");
strcat(modPathName, dirInfo->d_name);
struct stat statBuf;
struct stat otherStatBuf;
if (stat(basePathName, &statBuf) == -1)
{
/* error! */
fprintf(stderr, "stat() failed for '%s'", basePathName);
}
else
{
//display time
stat(modPathName, &otherStatBuf);
if (statBuf.st_mtime > otherStatBuf.st_mtime)
{
char date[36];
printf("Modify: %s\n", formatdate(date, otherStatBuf.st_mtime));
}
if (S_ISDIR(statBuf.st_mode))
{
/* if this is a directory, then recurse! */
greetDirectory(basePathName, modPathName);
}
else
{
/* else if it's a file, then greet it! */
printf("entry name = %s\n", modPathName);
}
}
}
}
closedir(directory);
}
Your code will give output only when you specify the -R switch.
If you do not want this behavior, you need to remove if block on line 72 and call greetDirectory function directly.
// Remove if block
if (R_switch)
{
greetDirectory(baseDir, modDir);
}
// Replace with
greetDirectory(baseDir, modDir);
Here is the full code:
#include <stdio.h>
#include <ctype.h>
#include <math.h>
#include <stdlib.h>
#include <dirent.h>
#include <errno.h>
#include <sys/stat.h>
#include <string.h>
#include <time.h>
#define E_INVALIDSWITCH 100
#define E_TOOMANYPARAMS 101
#define E_TOOFEWPARAMS 102
#define E_OPENDIRFAIL 103
#define MAX_DIR_NAME_SIZE 100
void status();
void greetDirectory(char * baseDir, char * modDir);
int main(int argc, char ** argv)
{
int R_switch = 0;
char modDir[MAX_DIR_NAME_SIZE] = {0};
char baseDir[MAX_DIR_NAME_SIZE] = {0};
int i;
for (i = 1; i < argc; i++)
{
if (argv[i][0] == '-')
{
if (strcmp(argv[i], "-R") == 0)
{
R_switch = 1;
continue;
}
else
{
fprintf(stderr, "Error: Invalid switch %s\n", argv[i]);
status();
return E_INVALIDSWITCH;
}
}
else
{
if (baseDir[0] == 0 && modDir[0] == 0)
{
strcpy(baseDir, argv[i]);
strcpy(modDir, argv[i]);
}
else
{
fprintf(stderr, "Error: Too many parameters\n");
status();
return E_TOOMANYPARAMS;
}
}
}
if (modDir[0] == 0)
{
fprintf(stderr, "Error: Too few parameters\n");
status();
return E_TOOFEWPARAMS;
}
if (R_switch)
{
greetDirectory(baseDir, modDir);
}
return 0;
}
void status()
{
printf("\t-R\tGreet all files in current directory\n");
printf("\t<modDir>\tName of person being greeted\n");
}
char *formatdate(char *buff, time_t val)
{
strftime(buff,200, "%d.%m.%Y %H:%M:%S", localtime(&val));
return buff;
}
void greetDirectory(char * baseDir, char * modDir)
{
DIR * directory;
struct dirent * dirInfo;
directory = opendir(baseDir);
if (directory == NULL)
{
fprintf(stderr,
"opendir() failed for '%s', errno=%d\n",
baseDir,
errno);
exit(E_OPENDIRFAIL);
}
while((dirInfo = readdir(directory)) != NULL)
{
if (strcmp(dirInfo->d_name, ".") != 0 &&
strcmp(dirInfo->d_name, "..") != 0)
{
/* BASE DIR*/
char basePathName[PATH_MAX];
strcpy(basePathName, baseDir);
strcat(basePathName, "/");
strcat(basePathName, dirInfo->d_name);
/* MOD DIR */
char modPathName[PATH_MAX];
strcpy(modPathName, modDir);
strcat(modPathName, "/");
strcat(modPathName, dirInfo->d_name);
struct stat statBuf;
struct stat otherStatBuf;
if (stat(basePathName, &statBuf) == -1)
{
/* error! */
fprintf(stderr, "stat() failed for '%s'", basePathName);
}
else
{
//display time
stat(modPathName, &otherStatBuf);
if (statBuf.st_mtime > otherStatBuf.st_mtime)
{
char date[36];
printf("Modify: %s\n", formatdate(date, otherStatBuf.st_mtime));
}
if (S_ISDIR(statBuf.st_mode))
{
/* if this is a directory, then recurse! */
greetDirectory(basePathName, modPathName);
}
else
{
/* else if it's a file, then greet it! */
printf("entry name = %s\n", modPathName);
}
}
}
}
closedir(directory);
}
The main problem was in your loop where you assign values to modDir and baseDir. Say, for example, you have the argument -R, so you want to print out the directory names. You assign R_switch a value of 1 since argv[1] is -R. The problem is, you go on in the loop to assign baseDir and modDir -R as well! This should have been done on the next iteration of the loop, when argv[2] is whatever directory you put in for input.
The very simple way to solve this problem is to add a continue; statement after you set R_switch a value of 1.
Also note that while playing around, I did create the limitation of having a MAX_DIR_NAME_SIZE, when it was not needed with the char * you were working with originally. It should be fairly easy to change this back. I also ended up changing the comparison of modDir and baseDir to something like if (baseDir[0] == 0 && modDir[0] == 0), which probably should have still been done by comparing your char * to NULL (like it was originally).
So, in this program I need to print the name of the file specified by the user when they run the program ./tstats input.txt. My problem is when I try to print out what the pointer is pointing too I get this: 84 18 407 ffbff2a4. Now I know exactly what the first 3 set of numbers are however that address I know has to with the pointer. I'm aware that my format for the print out needs to be in a string format however you can't print out a pointer in the format of a string. So here lies my question, how would you print out the name of the file by using what code I have now and my pointer to the input_from_args src?
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
enum state
{
START,
WORD,
DELIM,
};
FILE*
input_from_args(int argc, const char *argv[])
{
if (argc == 1) {
return stdin;
}
else {
return fopen(argv[1], "r");
}
}
void
wcount(FILE *src, FILE *dest)
{
int ch, wc, lc, cc;
enum state cstate;
wc = lc = cc = 0;
cstate = START;
while ((ch = fgetc(src)) != EOF){
cc++;
switch (cstate) {
case START:
if (isspace(ch)) {
cstate = DELIM;
if (ch == '\n') {
lc++;
}
}
else {
cstate = WORD;
wc++;
}
break;
case DELIM:
if (ch == '\n') {
lc++;
}
else if (!isspace(ch)) {
cstate = WORD;
wc++;
}
break;
case WORD:
if (isspace(ch)) {
cstate = DELIM;
if (ch == '\n') {
lc++;
}
}
break;
}
}
fprintf(dest, "%4d\t%4d\t%4d\t%10p\n", wc, lc, cc, &src);
}
int
main(int argc, const char *argv[])
{
FILE *src = input_from_args(argc, argv);
FILE *dest = stdout;
if (src == NULL) {
fprintf(stderr, "%s: unable to open %s\n", argv[0], argv[1]);
exit(EXIT_FAILURE);
}
wcount(src, dest);
fclose(src);
return EXIT_SUCCESS;
}
edit Question 2 code:
int
main(int argc, char* argv[])
{
int i;
FILE *src = input_from_args(argc, argv);
FILE *dest = stdout;
for (i = 1; i < argc; i++)
{
if ((src = fopen(argv[i], "r")) == NULL)
{
fprintf(stderr, "%s: unable to open %s\n", argv[0], argv[i]);
}
wcount(src, dest, get_filename_from_args(argc, argv[i]));
fclose(src);
}
return EXIT_SUCCESS;
}
My suggestion:
Create a function that returns the filename to be printed by wcount:
char* get_filename_from_args(int argc, char* argv[])
{
static char stdin_name[] = "-";
if (argc == 1) {
return stdin_name;
}
else {
return argv[1];
}
}
Change the signature of wcount:
void wcount(FILE *src, FILE *dest, char* src_filename)
Change the call to wcount:
wcount(src, dest, get_filename_from_args(argc, argv));
Change the implementation of the line in wcount where you write out the details:
fprintf(dest, "%4d\t%4d\t%4d\t%s\n", wc, lc, cc, src_filename);
I have to read a string from stdin, allocating memory dinamically without wasting it.
I've done this, but i'm not convinced about it,because in this way i think i waste memory!
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
char *alloc_memory(int n)
{
char *p;
p=malloc(n*sizeof(char));
if(p==NULL)
{
fprintf(stderr,"Error in malloc\n");
exit(EXIT_FAILURE);
}
return p;
}
int main(int argc, char *argv[])
{
if(argc != 1)
{
fprintf(stderr,"Usage: %s \n",argv[0]);
return EXIT_FAILURE;
}
char string[64];
int lung;
char *p,*s,*w;
printf("Insert string: \n");
p=fgets(string,63,stdin);
if(p==NULL)
{
fprintf(stderr,"Error in fgets\n");
exit(EXIT_FAILURE);
}
printf("You've inserted: %s", string);
lung=strlen(p);
s = alloc_memory(lung+1);
w=strncpy(s,p,lung);
printf("Final string:%s", w);
return EXIT_SUCCESS;
}
any idea? Should i read one character at a time?
To have char str[64] (string is not a good name for a variable, it might lead to ambiguities) declared only temporarily just put it in a local context:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
char * alloc_memory(size_t n)
{
char * p = malloc(n); /* * sizeof(char) is always 1 */
if (p == NULL)
{
fprintf(stderr, "Error in malloc() when trying to allocate %zu bytes.\n", n);
exit(EXIT_FAILURE);
}
memset(p, 0, n); /* Avoid having strncpy() choke .. later down in this example. */
return p;
}
int main(int argc, char * argv[])
{
if (argc != 1)
{
fprintf(stderr, "Usage: %s \n", argv[0]);
return EXIT_FAILURE;
}
{
char * w = NULL;
printf("Insert string: ");
{
char str[64]; /* here str is allocated */
char * p = fgets(str, 63, stdin);
if (p == NULL)
{
fprintf(stderr, "Error in fgets().\n");
exit(EXIT_FAILURE);
}
printf("You've inserted: '%s'\n", str);
{
size_t lung = strlen(p);
char * s = alloc_memory(lung + 1);
w = strncpy(s, p, lung);
}
} /* here "str" is deallocated */
printf("Final string: '%s'\n", w);
}
return EXIT_SUCCESS;
}
I am new to C and i am trying to iteratively call line in stream and check to see if it contains my search string or if it is null. I cant figure out how to make this check, i get a warning saying [Warning] comparison between pointer and integer or [Warning] assignment makes pointer from integer without a cast whenever i try and do this. can anyone help? thanks.
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char *argv[]) {
FILE *fpntr;
char *file_pathname, *first_line;
if (argc != 2) {
fprintf(stderr, "usage: %s FILE\n", argv[0]);
return EXIT_FAILURE;
}
file_pathname = argv[1];
if ((fpntr = fopen(file_pathname, "r")) == NULL ) {
fprintf(stderr, "Error opening file %s: %s\n", file_pathname, strerror(errno));
return EXIT_FAILURE;
} else {
grep_stream();
fclose(fpntr);
}
return EXIT_SUCCESS;
}
int grep_stream(FILE *fpntr, char *string, char *file_pathname) {
//warning is on next line
while ((? = get_next_line(fpntr)) == NULL ) {
perror("Error reading line");
exit(EXIT_FAILURE);
}
elseif()
{
printf("First line in : %s \n %s", file_pathname, string);
}
}
char *get_next_line(FILE *fpntr) {
char *buff = malloc(101);
int pos = 0;
int next;
while ((next = fgetc(fpntr)) != '\n' && next != EOF) {
buff[pos++] = next;
}
buff[pos] = '\0';
if (buff != NULL ) {
return buff;
} else
return NULL ;
}
Remember that C code is compiled top-to-bottom. The function get_next_line isn't declared by the time the while line is read.
Either move get_next_line's definition to before main's, or forward-declare it by saying:
char *get_next_line(FILE *fpntr);
beforehand. The reason that you're getting a warning instead of an error is that undeclared functions are assumed to return int and no assumptions are made about their parameters. That is, they have the type int().
Also, properly format your code for both your sake and of those who will be answering your questions (or working with you.)
add a * to the pointer of integer to convert it from pointer to integer
... i am trying to iteratively call line in stream...
Why not use fgets()?
Secondly, to match a substring in a string, you can use strstr()
Please use standard C library instead of re-inventing the wheel. It saves the day usually.
#include <assert.h> // I'm too dumb to program without assertions!
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
//#include <unistd.h> I prefer stdlib.h, couldn't see any need for non-portable header...
#define MAX_LINE (101) // define funky constants in one place for easy changing later.
// declare functions before using them
void grep_stream(FILE *fpntr, char *file_pathname);
char *get_next_line(FILE *fpntr);
int main(int argc, char *argv[]) {
FILE *fpntr;
char *file_pathname;
if (argc != 2) {
fprintf(stderr, "usage: %s FILE\n", argv[0]);
return EXIT_FAILURE;
}
file_pathname = argv[1];
if ((fpntr = fopen(file_pathname, "r")) == NULL ) {
fprintf(stderr, "Error opening file %s: %s\n", file_pathname, strerror(errno));
return EXIT_FAILURE;
}
else {
grep_stream(fpntr, file_pathname);
fclose(fpntr);
}
return EXIT_SUCCESS;
}
void grep_stream(FILE *fpntr, char *file_pathname) {
char* line;
int got_first = 0;
assert(fpntr);
assert(file_pathname); // I worry the guy who wrote main() might be an idiot like me!
//warning is on next line [not anymore!]
while ((line = get_next_line(fpntr)) != NULL ) {
if(!got_first) {
printf("First line in : %s \n%s\n", file_pathname, line);
got_first = 1;
}
// if we're not going to use it, let's not leak memory
free(line);
}
}
char *get_next_line(FILE *fpntr) {
char *buff = malloc(MAX_LINE);
int pos = 0;
int next;
assert(buff != NULL); // wouldn't it be nice to know malloc() worked?
while ((next = fgetc(fpntr)) != '\n' && next != EOF) {
buff[pos++] = (char)next;
assert(pos < (MAX_LINE-1)); // don't want to be right back on SO with a seg fault, eh?
}
buff[pos] = '\0';
if(next == EOF) {
free(buff);
buff = NULL;
}
return buff;
}