expected identifier or '(' before '~' token - c

I encountered a problem while working on a project. I know there are many simillar questions that are answered, but regarding this special one I could not find any help. I am getting the following error:
Compiling main.c
main.c:42:1: error: expected identifier or '(' before '~' token
~
^
Makefile:47: recipe for target 'obj/main.o' failed
make: *** [obj/main.o] Error 1
EDIT: I deleted the last lines of the code, but the error still occures at the line after the last '}'.
The project is about the PageRank Algorithm, using options in the console for choosing what algorithm is wished to be used. I am trying to read or use the options in the command line, but the error stops me from even looking at the semantic of my program.
/*
* main.c
*
*Programmierung 2 - Projekt 2 (PageRank)
*/
#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
#include "utils.h" //is existing in the Directory
int main (int argc, char *const *argv) {
//initialize the random number generator
rand_init();
printf("You gave %d command line arguments%c\n", argc-1, argc==1 ? '.' : ':');
int graph;
int i = 1;
char * h = "-h show this help. \n";
char * p = "...";
char * m = "...";
char * r = "...";
char * s = "...";
while ((graph = getopt(argc, argv, "hmprs")) != -1) {
switch (graph) {
default : printf("make -h | -m | -p | -r | -s "); break;
case 'h' : printf("%s %s %s %s %s"), h, m, p, r, s); break;
//this-like outcommended code like the one above
//and again
//and once more
//and a final one
}
printf(" - %s\n", argv[i]);
i++;
}
exit(0);
}
One more thing: I encountered a problem regarding the lengh of the case 'h' : printf(), so I outcoded the text in multiple chars.
If you need more information about anything, ask me.

The compiler reports an error on line 42, but the source in your question is only 33 lines and it contains no ~ character. You need to show us the entire source you're compiling.
But I have a good guess.
The error message shows a line with a ~ character in column 1 and nothing following it. The vi (or vim) text editor uses ~ to mark lines on the screen that aren't part of the file. If you copy-and-paste a source file from a vi editor session, it's easy to copy too many lines and end up with an extra ~ at the end of your source file.
Edit the file, jump to the end, and delete that line.

I got it now. My compiler (vim) added lines out of my sight. I used another editor and could delete the unnessecary code properly. Yes, was my bad all along. I am deeply sorry, it was a long day.

Related

Flex and Bison, Windows Error using symbol table

Program is intended to store values in a symbol table and then have them be able to be printed out stating the part of speech. Further to be parsed and state more in the parser, whether it is a sentence and more.
I create the executable file by
flex try1.l
bison -dy try1.y
gcc lex.yy.c y.tab.c -o try1.exe
in cmd (WINDOWS)
My issue occurs when I try to declare any value when running the executable,
verb run
it goes like this
BOLD IS INPUT
verb run
run
run
syntax error
noun cat
cat
syntax error
run
run
syntax error
cat run
syntax error
MY THOUGHTS: I'm unsure why I'm getting this error back from the code Syntax error. Although after debugging and trying to print out what value was being stored, I figured there has to be some kind of issue with the linked list. As it seemed only one value was being stored in the linked list and causing an error of sorts. As I tried to print out the stored word_type integer value for run and it would print out the correct value 259, but would refuse to let me define any other words to my symbol table. I reversed the changes of the print statements and now it works as previously stated. I think again there is an issue with the addword method as it isn't properly being added so the lookup method is crashing the program.
Lexer file, this example is taken from O'Reily 2nd edition on Lex And Yacc,
Example 1-5,1-6.
Am trying to learn Lex and Yacc on my own and reproduce this example.
%{
/*
* We now build a lexical analyzer to be used by a higher-level parser.
*/
#include <stdlib.h>
#include <string.h>
#include "ytab.h" /* token codes from the parser */
#define LOOKUP 0 /* default - not a defined word type. */
int state;
%}
/*
* Example from page 9 Word recognizer with a symbol table. PART 2 of Lexer
*/
%%
\n { state = LOOKUP; } /* end of line, return to default state */
\.\n { state = LOOKUP;
return 0; /* end of sentence */
}
/* whenever a line starts with a reserved part of speech name */
/* start defining words of that type */
^verb { state = VERB; }
^adj { state = ADJ; }
^adv { state = ADV; }
^noun { state = NOUN; }
^prep { state = PREP; }
^pron { state = PRON; }
^conj { state = CONJ; }
[a-zA-Z]+ {
if(state != LOOKUP) {
add_word(state, yytext);
} else {
switch(lookup_word(yytext)) {
case VERB:
return(VERB);
case ADJECTIVE:
return(ADJECTIVE);
case ADVERB:
return(ADVERB);
case NOUN:
return(NOUN);
case PREPOSITION:
return(PREPOSITION);
case PRONOUN:
return(PRONOUN);
case CONJUNCTION:
return(CONJUNCTION);
default:
printf("%s: don't recognize\n", yytext);
/* don't return, just ignore it */
}
}
}
. ;
%%
int yywrap()
{
return 1;
}
/* define a linked list of words and types */
struct word {
char *word_name;
int word_type;
struct word *next;
};
struct word *word_list; /* first element in word list */
extern void *malloc() ;
int
add_word(int type, char *word)
{
struct word *wp;
if(lookup_word(word) != LOOKUP) {
printf("!!! warning: word %s already defined \n", word);
return 0;
}
/* word not there, allocate a new entry and link it on the list */
wp = (struct word *) malloc(sizeof(struct word));
wp->next = word_list;
/* have to copy the word itself as well */
wp->word_name = (char *) malloc(strlen(word)+1);
strcpy(wp->word_name, word);
wp->word_type = type;
word_list = wp;
return 1; /* it worked */
}
int
lookup_word(char *word)
{
struct word *wp = word_list;
/* search down the list looking for the word */
for(; wp; wp = wp->next) {
if(strcmp(wp->word_name, word) == 0)
return wp->word_type;
}
return LOOKUP; /* not found */
}
Yacc file,
%{
/*
* A lexer for the basic grammar to use for recognizing English sentences.
*/
#include <stdio.h>
%}
%token NOUN PRONOUN VERB ADVERB ADJECTIVE PREPOSITION CONJUNCTION
%%
sentence: subject VERB object{ printf("Sentence is valid.\n"); }
;
subject: NOUN
| PRONOUN
;
object: NOUN
;
%%
extern FILE *yyin;
main()
{
do
{
yyparse();
}
while (!feof(yyin));
}
yyerror(s)
char *s;
{
fprintf(stderr, "%s\n", s);
}
Header file, had to create 2 versions for some values not sure why but code was having an issue with them, and I wasn't understanding why so I just created a token with the full name and the shortened as the book had only one for each.
# define NOUN 257
# define PRON 258
# define VERB 259
# define ADVERB 260
# define ADJECTIVE 261
# define PREPOSITION 262
# define CONJUNCTION 263
# define ADV 260
# define ADJ 261
# define PREP 262
# define CONJ 263
# define PRONOUN 258
If you feel that there is a problem with your linked list implementation, you'd be a lot better off testing and debugging it with a simple driver program rather than trying to do that with some tools (flex and bison) which you are still learning. On the whole, the simpler a test is and the fewest dependencies which it has, the easier it is to track down problems. See this useful essay by Eric Clippert for some suggestions on debugging.
I don't understand why you felt the need to introduce "short versions" of the token IDs. The example code in Levine's book does not anywhere use these symbols. You cannot just invent symbols and you don't need these abbreviations for anything.
The comment that you "had to create 2 versions [of the header file] for some values" but that the "code was having an issue with them, and I wasn't understanding why" is far too unspecific for an answer. Perhaps the problem was that you thought you could use identifiers which are not defined anywhere, which would certainly cause a compiler error. But if there is some other issue, you could ask a question with an accurate problem description (that is, exactly what problem you encountered) and a Minimal, Complete, and Verifiable example (as indicated in the StackOverflow help pages).
In any case, manually setting the values of the token IDs is almost certainly preventing you from being able to recognized inputs. Bison/yacc reserves the values 256 and 257 for internal tokens, so the first one which will be generated (and therefore used in the parser) has value 258. That means that the token values you are returning from your lexical scanner have a different meaning inside bison. Bottom line: Never manually set token values. If your header isn't being generated correctly, figure out why.
As far as I can see, the only legal input for your program has the form:
sentence: subject VERB object
Since none of your sample inputs ("run", for example) have this form, a syntax error is not surprising. However, the fact that you receive a very early syntax error on the input "cat" does suggest there might be a problem with your symbol table lookup. (That's probably the result of the problem noted above.)

Fail to scan integers from a text file

I have a text file that looks like that:
coordinate size average Intensity
========== ==== =================
(187,18) 31 217.8
(58,29) 34 212.1
(124,71) 47 216.1
(245,71) 32 197.8
(96,113) 30 191.6
(244,135) 33 199.6
Im trying to receive only the 'size' to a variable but for some reason im not able to do so. This is the code i tried:
FILE * textofGags;
int xx;
fopen_s(&textOfGags,"dust.txt","rt");
fseek(textOfGags,0L,SEEK_SET);
fscanf_s(textOfGags,"%*[^\n]\n,",NULL);
fscanf_s(textOfGags,"%*[^\n]\n,",NULL);
while(fscanf_s(textOfGags,"%d",&xx)==1){
printf("%d",xx);
fscanf_s(textOfGags,"%*[^\n]\n,",NULL);
}
For now im just trying to print in order to see where the problem is but it seems that i cant even receive the number. Can someone point out my mistake?
I suppose you got some downvotes for wrong tagging :-)
Anyway, I think we should help each other.
The code looks a little bit complicated to me, and - even with a debugger - it is probably hard to find out whether an fscanf("%*[^\n]\n," ... moves the file position actually to the right place;
I suggest to read in the file line by line, then analyse each line based on it's specific content, and read in the size. For example, one might use the fact that the size-value is the first integral value after a closing ')', and lines without such a ')' may be ignored.
Hope it helps :-)
int main() {
FILE * textofGags;
int xx;
textofGags = fopen("dust.txt","rt");
if (textofGags) {
char line[1000];
while (fgets(line,1000,textofGags)) {
char *closingBrace = strchr(line, ')');
if (!closingBrace)
continue;
closingBrace++; // first char after the ')'
if (sscanf(closingBrace,"%d",&xx) == 1) {
printf("size: %d \n", xx);
}
}
}
}

Properties file reading in C (no C# or C++) compiled with minGW

I need to say that i am Newbie at C and i only wrote about 100-150 lines of code in C.
I need to read a .properties file with entries like the following:
Value1 = Hello
Value2 = Bye
I would like to get to the Values like this:
bla.getValue("Value1");
So i can work with it like this:
foo = bla.getValue("Value1");
bar = bla.getValue("Value2");
printf("%s - %s",foo,bar);
I don't need them for anything else, than printing them to the screen.
I found two questions here, which went into the right direction, but they couldn't help me in my task:
How to read configuration/properties file in C?
Properties file library for C (or C++)
I tried multiple of the answers of the thread above, but either way my compiler(minGW) doesn't like one of these lines:
using foo::bar;
or
using namespace foo;
When i try to compile my code, i get an error saying:
error: unknown type name 'using'
This is the code where i tried to implement the given solution of the thread above:
#include <windows.h>
#include <stdio.h>
#include <string.h>
using platformstl::properties_file;
int WINAPI WinMain(HINSTANCE a,HINSTANCE b,LPSTR c,int d)
{
char *tPath, *tWindow;
char *search = " ";
tWindow = strtok(c, search);
tPath = strtok(NULL, search);
properties_file properties("%s",tPath);
properties::value_type value1 = properties["Value1"];
properties::value_type value2 = properties["Value2"];
printf("Window: %s; Path: %s; %s %s",tWindow,tPath,value0,value1);
}
I use a WinMain, because the programm is about finding an open Window. I haven't included those parts of the code, because they are irrelevant for my question and worked completely fine. The strtok(); parts are working fine for me too. I need them, because the title of the window to find and the Path of the properties file are both given as commandline arguments:
programm.exe windowtitle path/to/properties/file
As i tried with other answers, which told me to load some libraries, i got to a point, where the needed libraries didn't contain the needed header files. Some of the libraries are even for c++, which i have a restriction on, so i can't use it.
I hope that made things a little clearer, as you may know that i am not used to ask questions here. :)
I solved my Problem with a big Workaround.
This is my final code:
if(vn != NULL){
for(i = 0; i < 1; i++){
if(fgets(temp, BUF, vn) == NULL){
printf("Line is empty");
return 2;
}
}
if(fgets(puffer, BUF, vn) == NULL){
printf("Line is empty");
return 2;
}
tVariable = strtok(puffer, find);
tValue = strtok(NULL, find);
}else {
printf("Unable to read File");
return 2;
}
I just read the second Line of the given file and cut it at the = sign.
I know, that i need to read the second line, because the Property i need is always found in the second line of the .properties file.
I now have my wanted Value in tValue, so i can use it to print it out with printf("%s", tValue).

Filter text from huge .csv files, in C

I have the raw and unfiltered records in a csv file (more than 1000000 records), and I am suppose to filter out those records from a list of files (each weighing more than 282MB; approx. more than 2000000 records). I tried using strstr in C. This is my code:
while (!feof(rawfh)) //loop to read records from raw file
{
j=0; //counter
while( (c = fgetc(rawfh))!='\n' && !feof(rawfh)) //read a line from raw file
{
line[j] = c; line[j+1] = '\0'; j++;
}
//function to extract the element in the specified column, in the CSV
extractcol(line, relcolraw, entry);
printf("\nWorking on : %s", entry);
found=0;
//read a set of 4000 bytes; this is the target file
while( fgets(buffer, 4000, dncfh)!=NULL && !found )
{
if( strstr(buffer, entry) !=NULL) //compare it
found++;
}
rewind(dncfh); //put the file pointer back to the start
// if the record was not found in the target list, write it into another file
if(!found)
{
fprintf(out, "%s,\n", entry); printf(" *** written to filtered ***");
}
else
{
found=0; printf(" *** Found ***");
}
//I hope this is the right way to null out a string
entry[0] = '\0'; line[0] ='\0';
//just to display a # on the screen, to let the user know that the program
//is still alive and running.
rawreccntr++;
if(rawreccntr>=10)
{
printf("#"); rawreccntr=0;
}
}
This program takes approximately 7 to 10 seconds, on an average, to search one entry in the target file (282 MB). So, 10*1000000 = 10000000 seconds :( God knows how much is that going to take if I decide to search in 25 files.
I was thinking of writing a program, and not going to spoon fed solutions (grep, sed etc.). OH, sorry, but I am using Windows 8 (64 bit, 4 GB RAM, AMD processor Radeon 2 core - 1000Mhz). I used DevC++ (gcc) to compile this.
Please enlighten me with your ideas.
Thanks in advance, and sorry if I sound stupid.
Update by Ali, the key information extracted from a comment:
I have a raw CSV file with details for customer's phone number and address. I have the target file(s) in CSV format; the Do Not Call list. I am suppose to write a program to filter out phone number that are not present in the Do No Call List. The phone numbers (for both files) are in the 2nd column. I, however, don't know of any other method. I searched for Boyer-Moore algorithm, however, could not implement that in C. Any suggestions about how should I go about searching for records?
EDITED
I would recommend you have a try with the readymade tools in any Unix/Linux system, grep and awk. You'll probably find they are just as fast and much more easily maintained. I haven't seen your data format, but you say the phone numbers are in the second column, so you can get the phone numbers on their own like this:
awk '{print $2}' DontCallFile.csv
If your phone numbers are in double quotes, you can remove those like this:
awk '{print $2}' DontCallFile.csv | tr -d '"'
Then you can use fgrep with the -f option, to search whether strings listed in one file are present in a second file, like this:
fgrep -f file1.csv file2.csv
or you can invert the search and search for strings NOT present in another file, by adding the -v switch to fgrep.
So, your final command would probably end up like this:
fgrep -v -f <(awk '{print $2}' DontCallFile.csv | tr -d '"') file2.csv
That says... search, in file2.csv for all strings not present (-v option) in column 2 of file "DontCallFile.csv". If you want to understand the bit in <() it is called process substitution and it basically makes a pseudo-file out of the result of running the command inside the brackets. And we need a pseudo-file because fgrep -f expects a file.
ORIGINAL ANSWER
Why are you using fgetc() anyway. Surely you would use getline() like this:
while(getline(myfile,line ))
{
...
}
Are you really reading the whole "target" file from the start for every single line in your main file? That will kill you! And why are you doing it in chunks of 4,000 bytes? And what if one of your strings straddles the 4,000 bytes you compare it with - i.e. the first 8 bytes are in one 4k chunk and the last however many bytes are in the nect 4k chunk?
I think you will get better help on here if you take the time to explain properly what you are trying to do - and maybe do it with awk or grep (at least figuratively) so we can see what you are actually trying to achieve. Your decription doesn't mention the "target" file you use in the code, for example.
You can do this with awk, like this:
awk -F, '
FNR==NR {gsub(/"/,"",$2);dcn[$2]++;next}
{gsub(/ /,"",$2);if(!dcn[$2])print}
' DontCallFile.csv x.csv
That says... the field separator is a comma (-F,). Now read the first file (DontCallFile.csv) and process according to the part in curly braces after FNR==NR. Remove the double quotes from around the phone number in field 2, using gsub (global substitution). Then increment the element in the associative array (i.e. hash) as indexed by unquoted field 2 and then move to next record. So basically, after file "DontCallFile.csv" is processed, the array dcn[] will hold a hash of all the numbers not to call (dcn=dontcallnumbers). Then, the code in the second set of curly braces is executed for each line of the second file ("x.csv"). That says... remove all spaces from around the phone number in field 2. Then, if that phone number is not present in the array dcn[] that we built earlier, print the line.
Here is one idea for improvement...
In the code below, what's the point in setting line[j+1] = '\0' at every iteration?
while( (c = fgetc(rawfh))!='\n' && !feof(rawfh))
{
line[j] = c; line[j+1] = '\0'; j++;
}
You might as well do it outside the loop:
while( (c = fgetc(rawfh))!='\n' && !feof(rawfh))
line[j++] = c;
line[j] = '\0';
My advice is the following.
Put all don't call phone numbers into an array.
Sort this array.
Use binary search to check if a given phone number is among the sorted
don't call numbers.
In the code below, I just hard-coded the numbers. In your application, you will have to replace that with the corresponding code.
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int compare(const void* a, const void* b) {
return (strcmp(*(char **)a, *(char **)b));
}
int binary_search(const char** first, const char** last, const char* val) {
ptrdiff_t len = last - first;
while (len > 0) {
ptrdiff_t half = len >> 1;
const char** middle = first;
middle += half;
if (compare(&*middle, &val)) {
first = middle;
++first;
len = len - half - 1;
}
else
len = half;
}
return first != last && !compare(&val,&*first);
}
int main(int argc, char** argv) {
size_t i;
/* Read _all_ of your don't call phone numbers into an array. */
/* For the sake of the example, I just hard-coded it. */
char* dont_call[] = { "908-444-555", "800-200-400", "987-654-321" };
/* in your program, change length to the number of dont_call numbers actually read. */
size_t length = sizeof dont_call / sizeof dont_call[0];
qsort(dont_call, length, sizeof(char *), compare);
printf("The don\'t call numbers sorted\n");
for (i=0; i<length; ++i)
printf("%lu %s\n", i, dont_call[i]);
/* For each phone number, check if it is in the sorted dont_call list. */
/* Use binary search to check it. */
char* numbers[] = { "999-000-111", "333-444-555", "987-654-321" };
size_t n = sizeof numbers / sizeof numbers[0];
printf("Now checking if we should call a given number\n");
for (i=0; i<n; ++i) {
int should_call = binary_search((const char **)dont_call, (const char **)dont_call+length, numbers[i]);
char* as_text = should_call ? "no" : "yes";
printf("Should we call %s? %s\n",numbers[i], as_text);
}
return 0;
}
This prints:
The don't call numbers sorted
0 800-200-400
1 908-444-555
2 987-654-321
Now checking if we should call a given number
Should we call 999-000-111? yes
Should we call 333-444-555? yes
Should we call 987-654-321? no
The code is definitely not perfect but it is sufficient to get you started.
The problem with your algorithm is complexity. You approach is O(n*m) where n is number of customers and m is number of do_not_call records (or size of file in your case). You need reduce this complexity. (And Boyer-Moore algorithm would not help there which suggested by Ali. It would not improve asymptotic complexity but only constant.) Even binary search as Ali suggest in his answer is not best. It would be O((n+m)*log m). We can do better. Nice solutions are using fgrep and awk as suggested by Mark Setchell in his answers. (I would chose one using fgrep which should perform better I guess but it is only guess.) I can provide one similar solution in Perl which will provide more robust CSV parsing and should handle your data sizes in easy on decent HW. This type of solutions has complexity O(n+m).
#!/usr/bin/env perl
use strict;
use warnings;
use autodie;
use Text::CSV_XS;
use constant PHN_COL_DNC => 1;
use constant PHN_COL_CUSTOMERS => 1;
die "Usage: $0 dnc_file [customers]" unless #ARGV>0;
my $dncfile = shift #ARGV;
my $csv = Text::CSV_XS->new({eol=>"\n", allow_whitespace=>1, binary=>1});
my %dnc;
open my $dnc, '<', $dncfile;
while(my $row = $csv->getline($dnc)){
$dnc{$row->[PHN_COL_DNC]} = undef;
}
close $dnc;
while(my $row = $csv->getline(*ARGV)){
$csv->print(*STDOUT, $row) unless exists $dnc{$row->[PHN_COL_CUSTOMERS]};
}
If it would not meet our performance expectation you can go down to C road but I would definitely recommend use some good csv parsing and hashmap libraries. I would try libcsv and khash.h

print concat value of newline("\n") result shows as <?> symbol in C

I have a code below
#include <stdio.h>
int main()
{
char *price_c = "200";
char *s_att = "test ";
int satt=strlen(s_att);
int price_len = strlen(price_c);
int send_attach_len = price_len+satt;
size_t length = send_attach_len +2;
char *concat = malloc(sizeof(char) *length);
snprintf(concat, length, "%s%s%s", s_att, price_c, "\n");
printf("value of concat is %s", concat);
}
when I see the value printed, I have only test 200 , but on some other occasion, I have test 200 < ? > where < ? > is a weird symbol, somehow the new line is not recognised.
But it is very strange because not all the time this weird symbol is shown up..
It just came up randomly. I am using ubuntu 10.04
Can anyone help me to solve this new line problem, so that it shows new line, and not weird symbol. Or maybe I can change the approach to concat the above value so that the new line is rendered correctly, and not showing a weird symbol?
The code looks ok, except for the very important fact that you are missing some headers.
strlen is in <string.h>, and malloc is in <stdlib.h>.
Include those, turn on your compiler warnings (-Wall for GCC), change your main signature to:
int main(void) { }
and actually return an int from it (or compile as C99, std=c99 for GCC), and the problems should go away.

Resources