int main(int argc, char *argv[])
{
MYAPP MyApp;
MyApp = (struct MyApp*)malloc(sizeof(struct MyApp));
MyApp->maxMovieYear = 0;
MyApp->maxMovieNum = 0;
MyApp->myYearTree = CreateTreeYear();
MyApp->myTree = CreateTree();
MyApp = read_data(argv,MyApp);
int exit=FALSE;
int command;
char title[256];
int year;
int imdbID;
char posterlink[512];
printf(">>>Welcome to Movie Analysis at IMDB<<< \n");
while (!exit)
{
printf("\n-Menu-\n\
1. Display the full index of movies\n\
2. Display the movies where their title contains a specific keyword\n\
3. Display the year with maximum number of movies\n\
4. Exit\n\
Option:");
if(MyApp == NULL){
exit = TRUE;
printf("\nCannot locate the file!");
break;
}
YearWithMostMovies(MyApp->myYearTree ,MyApp);
scanf("%d", &command);
fflush(stdin);
char searchSong[512];
switch (command)
{
case 1:
printf("Movie Index\n-------------\n");
display_index(MyApp->myTree);
break;
case 2:
printf("Please enter the movie you want to see: ");
scanf("%s",searchSong);
display_movies_keyword(MyApp->myTree,searchSong);
break;
case 3:
most_popular_year_movies(MyApp);
break;
case 4:
exit = TRUE;
break;
default:
printf("command not recognized\n");
break;
}
}
printf("\n");
return 0;
}
MYAPP read_data(char *argv[],MYAPP MyApp){
FILE *outfile = fopen(argv[1],"r");
AVLTree newNode = NULL;
if(outfile == NULL)
{
printf("File does not exist...\n");
return NULL;
}
int delimiterCount = 0;
char inputData[2001];
while((fgets(inputData,2001,outfile)) != NULL)
{
int len = strlen(inputData);
if (len >= 0 && inputData[len-1] == '\n')
inputData[--len] = '\0';
AVLTree temp = NULL;
//initialize the newNode
temp = (struct tree*)malloc(sizeof(struct tree));
temp->height = 0;
temp->left = NULL;
temp->right = NULL;
char* token = strtok(inputData, ",");
strcpy(temp->title,token);
while (token != NULL)
{
token = strtok(NULL, ",");//reading the rest of the tokens with strtok
delimiterCount++;
switch (delimiterCount) // this switch orders the tokens by their places
{
case 1:
strcpy(temp->year,token);
break;
case 2:
strcpy(temp->imdbID,token);
break;
case 3:
strcpy(temp->posterlink,token);
break;
}
}
newNode = temp;
MyApp->myTree = InsertElement(newNode,MyApp->myTree);
int x = atoi(newNode->year);
MyApp->myYearTree = InsertElementYear(x,MyApp->myYearTree);
delimiterCount = 0;
}
fclose(outfile);
return MyApp;
}
My struct definitions are:
typedef struct tree * AVLTree;
typedef struct year *AVLYear;[enter image description here][1]
struct tree{
char title[512];
char posterlink[1024];
char imdbID[512];
char year[512];
struct tree* left;
struct tree* right;
int height;
};
struct MyApp{
AVLTree myTree;
AVLYear myYearTree;
int maxMovieYear;
int maxMovieNum;
};
typedef struct MyApp* MYAPP;
typedef struct year *AVLYear;
struct year
{
int year;
int num;
AVLYear left;
AVLYear right;
int height;
};
when i am trying to get filename as argument fopen returns me this
**<msvcrt!_iob+96>**
what might be causing this problem?
my aim is to get the data from a file and put it in 2 different avltree's, i keep my trees in another struct called MYAPP to pass between functions easily. can it be the problem?
i could not see the cause of this error.
Edit: i am using my own header files for struct definitions and functions. also including:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "AVLTree.h"
#include "AVLYear.h"
thanks.
It seems you are running the program in your debugger. When you come at the fopen statement/call, the debugger shows you what fopen returned.
remember that fopen returns zero upon error, or a pointer to an open file structure. Since it does not return zero, it must have returned a pointer.
But your debugger wants to tell you where it is pointing to, and that is to the symbol msvcrt!_iob offset with 96 bytes. The seems like a valid structure, iob meaning something like "I/O buffer", or whatever the Microsoft programmer intended for that abreviation.
Conclusion: there is no error.
Related
I am trying to make a C program to take in a list of movies and add to it with memory alloction and able to retrieve movies from the list as well using a txt file.
movies.txt
5
Mission Impossible
Action
4
2008
Up
Action
3
2012
I keep running into an error after running in the command line and when the menu comes up, whenever I input something it runs a seg fault. I don't have access to a debugger right now and I'm not exactly sure what's wrong although I assume its a problem with my pointers or memory alloc.
Can someone point me in the right direction?
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
// limit definition
#define LIMIT 999
//movie structure
struct movie
{
char name[100];
char type[30];
int rating;
int releaseDate;
};
//reads file
void readFile(FILE *fp,struct movie* movieList[],int *noOfReviews)
{
char buffer[100];
int counter = 0;
struct movie* newNode;
fgets(buffer,LIMIT,fp);
*noOfReviews = atoi(buffer); // number of reviews in buffer
printf("%d",*noOfReviews); //prints reviews
while((fgets(buffer,LIMIT,fp)!=NULL) || (*noOfReviews > 0)) //if null or reviews greater than zero
{
if(counter % 4 == 0)
{
struct movie* tmpNode = (struct movie*)malloc(sizeof(struct movie)); //allocates memory
movieList[counter] = tmpNode;
newNode = tmpNode;
*noOfReviews--; // --#ofreviews
}
//copys struc into buffer
switch(counter % 4 )
{
case 0:
strcpy(newNode->name,buffer);
break;
case 1:
strcpy(newNode->type,buffer);
break;
case 2:
newNode->rating = atoi(buffer);
break;
case 3:
newNode->releaseDate = atoi(buffer);
break;
default:
printf("Exception\n");
break;
}
counter++;
}
}
//searches list
int searchList(struct movie* movielist[],char movieName[],int noOfMovies)
{
int counter = 0;
while(noOfMovies--)
{
if(strcmp(movielist[counter]->name,movieName) == 0) // if string compares to name
{
return counter;
}
counter++;
}
return -1;
}
//compares strings of name
int nameStrCmp(const void *a, const void *b)
{
return (strcmp(((struct movie*)a)->name,((struct movie*)b)->name));
}
// compares rating strings
int ratingStrCmp(const void * a, const void * b)
{
return (((struct movie*)a)->rating - ((struct movie*)b)->rating);
}
//displays the structure
void display(struct movie* movieList[],int n)
{
int i;
struct movie* searchRslt;
for(i = 0; i < n; i++)
{
searchRslt = movieList[i];// search result index of movies list
//prints struct information
printf("name:%s\n type:%s\n rating:%d\n releaseDate:%d\n",searchRslt->name,searchRslt->type,searchRslt->rating,searchRslt->releaseDate);
}
}
//main function
int main(int argc, char *argv[])
{
char buffer[100];
int noOfReviews;
struct movie* movieList[1000];
struct movie *searchRslt;
char mName[100];
if(argc <= 1)
{
printf("invalid");
return 0;
}
FILE *fp = fopen(argv[1],"r");
readFile(fp,movieList,&noOfReviews);
while(1)
{
//case selection menu
int input;
printf("Enter 1 to search for a movie.\n");
printf("Enter 2 to display the list of movies by name.\n");
printf("Enter 3 to display the list of movies by rating.\n");
scanf("%d",&input);
switch(input)
{
case 1:
printf("Enter movie name to search:");
scanf("%s",mName);
int index = searchList(movieList,mName,noOfReviews);
if(index < 0)
printf("Not found!!\n"); // if movie not found
else // gets movies
{
searchRslt = movieList[index];
printf("name:%s\n type:%s\n rating:%d\n releaseDate:%d\n",searchRslt->name,searchRslt->type,searchRslt->rating,searchRslt->releaseDate);
}
break;
case 2:
qsort(movieList,noOfReviews,sizeof(struct movie),nameStrCmp);
display(movieList,noOfReviews);
break;
case 3:
qsort(movieList,noOfReviews,sizeof(struct movie),ratingStrCmp);
display(movieList,noOfReviews);
break;
default:
break;
}
}
}
A few formatting/readability/coding suggestions: (Some are just suggestions, others actually eliminate warnings.)
format. (mainly indention)
replace 'struct movie' with MOVIE everywhere. (see struct definition below)
initialize variables before use.
pay attention to buffer size in declaration and usage (fgets errors)
Compile with warnings on. (eg, with gcc use -Wall)
The following is limited to addressing each of these items, including new struct definition. The following compiles and builds without warnings or errors. It does not include debugging your code. (If can do a Beyond Compare (its free), between your original post and the edited version below, you can easily find where the edits are.)
(At the time of this post, there was no information provided about your input file, so further efforts were not made.)
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
// limit definition
#define LIMIT 999
//movie structure
typedef struct {
char name[100];
char type[30];
int rating;
int releaseDate;
}MOVIE;
//reads file
void readFile(FILE *fp,MOVIE* movieList[],int *noOfReviews)
{
char buffer[LIMIT];
int counter = 0;
MOVIE* newNode = {0};
fgets(buffer,LIMIT,fp);
*noOfReviews = atoi(buffer); // number of reviews in buffer
printf("%d",*noOfReviews); //prints reviews
while((fgets(buffer,LIMIT,fp)!=NULL) || (*noOfReviews > 0)) //if null or reviews greater than zero
{
if(counter % 4 == 0)
{
MOVIE* tmpNode = (MOVIE *)malloc(sizeof(MOVIE)); //allocates memory
movieList[counter] = tmpNode;
newNode = tmpNode;
*noOfReviews--; // --#ofreviews
}
//copys struc into buffer
switch(counter % 4 ) {
case 0:
strcpy(newNode->name,buffer);
break;
case 1:
strcpy(newNode->type,buffer);
break;
case 2:
newNode->rating = atoi(buffer);
break;
case 3:
newNode->releaseDate = atoi(buffer);
break;
default:
printf("Exception\n");
break;
}
counter++;
}
}
//searches list
int searchList(MOVIE* movielist[],char movieName[],int noOfMovies)
{
int counter = 0;
while(noOfMovies--)
{
if(strcmp(movielist[counter]->name,movieName) == 0) // if string compares to name
{
return counter;
}
counter++;
}
return -1;
}
//compares strings of name
int nameStrCmp(const void *a, const void *b)
{
return (strcmp(((MOVIE*)a)->name,((MOVIE*)b)->name));
}
// compares rating strings
int ratingStrCmp(const void * a, const void * b)
{
return (((MOVIE*)a)->rating - ((MOVIE*)b)->rating);
}
//displays the structure
void display(MOVIE* movieList[],int n)
{
int i;
MOVIE* searchRslt;
for(i = 0; i < n; i++)
{
searchRslt = movieList[i];// search result index of movies list
//prints struct information
printf("name:%s\n type:%s\n rating:%d\n releaseDate:%d\n",searchRslt->name,searchRslt->type,searchRslt->rating,searchRslt->releaseDate);
}
}
//main function
int main(int argc, char *argv[])
{
int noOfReviews;
MOVIE* movieList[1000];
MOVIE *searchRslt;
char mName[100];
if(argc <= 1)
{
printf("invalid");
return 0;
}
FILE *fp = fopen(argv[1],"r");
readFile(fp,movieList,&noOfReviews);
while(1)
{
//case selection menu
int input;
printf("Enter 1 to search for a movie.\n");
printf("Enter 2 to display the list of movies by name.\n");
printf("Enter 3 to display the list of movies by rating.\n");
scanf("%d",&input);
switch(input)
{
case 1:
printf("Enter movie name to search:");
scanf("%s",mName);
int index = searchList(movieList,mName,noOfReviews);
if(index < 0)
printf("Not found!!\n"); // if movie not found
else // gets movies
{
searchRslt = movieList[index];
printf("name:%s\n type:%s\n rating:%d\n releaseDate:%d\n",searchRslt->name,searchRslt->type,searchRslt->rating,searchRslt->releaseDate);
}
break;
case 2:
qsort(movieList,noOfReviews,sizeof(MOVIE),nameStrCmp);
display(movieList,noOfReviews);
break;
case 3:
qsort(movieList,noOfReviews,sizeof(MOVIE),ratingStrCmp);
display(movieList,noOfReviews);
break;
default:
break;
}
}
}
I am trying to make a C program to count the number of frequency of words in a document and to split the document up into N parts with each part being counted by a different thread. Everytime I run the program, I get back nonsensical data, but if I run it without the threads I get back the data that I expect.
Here is the Struct named BinarySearchTree.h
typedef struct {
char *num; /*! The contents of the <tt>Item</tt>.<br>Type: <tt>int</tt>*/
int count;
} Item; /*! \typedef Item
* \struct A struct represent one item.
*/
typedef struct node {
Item info; /*! A struct with a one <tt>int</tt> on it. */
struct node * left;
struct node * right;
} Tree;
typedef struct passargs {
char *File;
Tree *t;
int splitStart;
int splitEnd;
int i;
int a;
char words[512][512];
} pass;
Here is the main code named **BinarySearchTree.c*:
#include "BinarySearchTree.h"
#include <pthread.h>
#include <string.h>
pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;
// Code for integer based BST from: https://gist.github.com/ArnonEilat/4611213
Tree * add(Tree* nod, char *number) {
if (nod == NULL) {
printf("Thread number %ld\n", pthread_self());
printf("\nMaking new node for %s\n", number);
nod = (Tree*) malloc(sizeof (Tree));
if (nod == NULL) {
return NULL;
}
nod->info.num = number;
nod->info.count=1; //Increment the value if the same word is found
nod->left = NULL;
nod->right = NULL;
return nod;
}
if (strcmp(nod->info.num, number)==0) {
printf("%s==%s ",nod->info.num,number);
printf("\t%s:%d ",nod->info.num,nod->info.count);
// ++nod->info.count;
nod->info.count++;
printf("->%d\n ",nod->info.count);
return nod;
}
if (strcmp(nod->info.num, number)>0){
printf("%s>%s ",nod->info.num,number);
nod->left = add(nod->left, number);
} else {
printf("%s<=%s ",nod->info.num,number);
nod->right = add(nod->right, number);
}
return nod;
}
void printInorder(Tree* nod) {
if (nod == NULL) {
return;
}
printInorder(nod->left);
printf(" %s: %d ", nod->info.num, nod->info.count);
printInorder(nod->right);
}
void freeTree(Tree *root) {
if (root == NULL) {
return;
}
freeTree(root->left);
freeTree(root->right);
free(root);
}
int newLines(char* File){ //Count the number of new lines in the file. Split based on those not word count
int newLines=0;
char buffTemp[5120];
FILE *fp1 = fopen(File, "r");
while(1)
{
if(fgets(buffTemp, 512, fp1) ==NULL)
break;
else{
newLines++;
}
}
fclose(fp1);
return newLines;
}
//This function reads the file and adds each entry to the tree, or increments if same word is present
Tree* read(pass* info){
const char *delims = " \n"; //Deliminate by newlines and spaces
char *token;
int splitCounter=0;
FILE *fp = fopen(info->File, "r");
char buff[512];
int aT=info->a; //Putting variables into local ones
int iT=info->i;
int splitEnd = info->splitEnd;
int splitStart = info->splitStart;
char words[512][512];
memcpy(words, info->words, 512);
Tree* nod=info->t;
while(1 && splitCounter<splitEnd) //While the file does not end and we have not reached the end of the split
{
fgets(buff, 512, fp);
splitCounter++;
if(buff == NULL)
break;
else if (splitCounter>splitStart){
printf("\t %s\n", buff);
token = strtok(buff, delims); //Split via the tokens and put them into buff
while (token!=0) {
strcpy(words[iT], token);
iT += 1;
token = strtok(NULL, delims);
}
}
}
for (;aT<iT;aT++){
nod=add(nod, (char *)words[aT]); //Add each word to the tree
}
printf("\n");
fclose(fp);
info->t=nod;
memcpy(info->words,words,512);
info->i=iT;
info->a=aT;
return nod;
}
int main() {
Tree* t = NULL;
pass args;
args.t=t;
args.i=0;
args.a=0;
args.splitStart=0; //These splits are used to tell each thread where to look in the file
args.splitEnd=0;
args.File="/home/dib/CLionProjects/deleteme/readFile"; //Address of the file to be read
int numLines=newLines(args.File);
printf("\nnewLines %d\n",numLines);
int split;
printf("How many splits/threads would you like to create?\n");
scanf("%d", &split);
int iterator=numLines/split;
printf("iterator %d:", iterator);
const int NUMTHREADS= numLines/iterator + (numLines % iterator != 0);
unsigned int p;
// This for loop shows how I hope the threads would work. Uncomment the below block to see it work
for (p=0; p<NUMTHREADS; p++){
args.splitStart=args.splitEnd;
if (args.splitEnd+iterator>numLines) args.splitEnd=numLines;
else args.splitEnd+=iterator;
read(&args);
}
pthread_t th[NUMTHREADS];
int threads[NUMTHREADS];
//This is my attempt at using threads to solve the same problem as the above for loop
// for(p=0; p< NUMTHREADS; p++){
// threads[p] = p;
// args.splitStart=args.splitEnd;
// if (args.splitEnd+iterator>numLines) args.splitEnd=numLines;
// else args.splitEnd+=iterator;
// printf("split end: %d",args.splitEnd);
// pthread_create(&th[p], NULL, &read, &args);
// }
printInorder(args.t);
freeTree(args.t);
exit(0);
}
And finally the document I have been using as a test case named readFile:
five five five one two
two three three four four
three six seven six six
four six five seven seven
seven seven seven seven six
five four six
I tried implementing the solution found here : passing struct to pthread as an argument
but did not know what thread_handles was, and could not get it to work though the problem faced in that link is similar. So am I also just having a problem with memory allocation or is it something completely different?
I have a word "all" in my trie and a word "alter" but "alt" is not a word in the trie. But when I check for "alt" it still returns true because is_word is true as "all" was a word. How am is supposed to work this error.
//Here's the code
typedef struct node{
bool is_word;
struct node *children[27];
} node;
unsigned int wsize=0;
node * root;
bool check(const char* word)
{
// TODO
node *chrawler=root;
for(int i=0;i<strlen(word)-1;i++)
{
int t;
if(word[i]>=65&&word[i]<=90)
{
t=word[i]-'A';
}
else if(isalpha(word[i]))
t=word[i]-'a';
else
t=26;
if(chrawler->children[t]==NULL)
return false;
else
chrawler=chrawler->children[t];
}
if(chrawler->is_word)
return true;
return false;
}
// Load function
bool load(const char* dictionary)
{
// TODO
FILE *inptr=fopen(dictionary,"r");
if(inptr==NULL)
{
return false;
}
node *new_node=malloc(sizeof(node));
root=new_node;
char * word=malloc((LENGTH+1)*sizeof(char));
int index=0;
for(int c=fgetc(inptr);c!=EOF;c=fgetc(inptr))
{
char ch=c;
if(ch=='\n')
{
word[index]='\0';
index=0;
node *chrawler=root;
for(int i=1;i<strlen(word);i++)
{
int t;
if(isalpha(word[i-1]))
t=word[i-1]-'a';
else
t=26;
if(chrawler->children[t]==NULL)
{
node *new_node=malloc(sizeof(node));
chrawler->children[t]=new_node;
chrawler=chrawler->children[t];
}
else
chrawler=chrawler->children[t];
}
chrawler->is_word=1;
wsize++;
}
else
{
word[index]=ch;
index++;
}
}
return true;
}
You need to ensure that all the pointers in a new node are null, as well as setting the is_word value to false. This is, perhaps, most easily done by using calloc() to allocate the space. Creating a function to allocate and error check the allocation of a node makes it easier. Similarly, you have two blocks of code mapping characters to trie indexes. You should use functions — even small ones — more generously.
The character-by-character input for a line of data is not really necessary, either; it would be better to use fgets() to read lines.
Adding these and sundry other changes (for example, local array word instead of dynamically allocated array — which wasn't freed; closing the file when finished; etc.) gives an MCVE (Minimal, Complete, Verifiable Example) like this:
#include <ctype.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
enum { LENGTH = 256 };
// Here's the code
typedef struct node
{
bool is_word;
struct node *children[27];
} node;
unsigned int wsize = 0;
node *root;
static inline int map_char(unsigned char c)
{
int t;
if (isalpha(c))
t = tolower(c) - 'a';
else
t = 26;
return t;
}
static inline node *alloc_node(void)
{
node *new_node = calloc(1, sizeof(node));
if (new_node == 0)
{
fprintf(stderr, "Memory allocation failed in %s\n", __func__);
exit(1);
}
return new_node;
}
static bool check(const char *word)
{
node *chrawler = root;
int len = strlen(word);
for (int i = 0; i < len; i++)
{
int t = map_char(word[i]);
if (chrawler->children[t] == NULL)
return false;
else
chrawler = chrawler->children[t];
}
return chrawler->is_word;
}
// Load function
static bool load(const char *dictionary)
{
FILE *inptr = fopen(dictionary, "r");
if (inptr == NULL)
{
fprintf(stderr, "Failed to open file '%s' for reading\n", dictionary);
return false;
}
root = alloc_node();
char word[LENGTH];
while (fgets(word, sizeof(word), inptr) != 0)
{
word[strcspn(word, "\n")] = '\0';
printf("[%s]\n", word);
node *chrawler = root;
int len = strlen(word);
for (int i = 0; i < len; i++)
{
int t = map_char(word[i]);
//printf("t = %d (%c)\n", t, word[i]);
if (chrawler->children[t] == NULL)
chrawler->children[t] = alloc_node();
chrawler = chrawler->children[t];
}
chrawler->is_word = 1;
wsize++;
}
printf("%d words read from %s\n", wsize, dictionary);
fclose(inptr);
return true;
}
int main(void)
{
const char *wordfile = "words.txt";
if (load(wordfile))
{
char line[4096];
while (fgets(line, sizeof(line), stdin) != 0)
{
line[strcspn(line, "\n")] = '\0';
if (check(line))
printf("[%s] is a word\n", line);
else
printf("[%s] is unknown\n", line);
}
}
return 0;
}
There are other changes that should be made. For example,
the wsize variable should be made non-global; it isn't really used outside the load() function. It's easily arguable that the root node should not be global either; the load() function should return the root node, and the check() function should be passed the root node. In general, global variables should be avoided when possible, and it is usually possible.
Given a file words.txt containing:
abelone
abyssinia
archimedes
brachiosaurus
triceratops
all
alter
asparagus
watchamacallit
a
abracadabra
abyss
ant
the output from a run of the program is:
[abelone]
[abyssinia]
[archimedes]
[brachiosaurus]
[triceratops]
[all]
[alter]
[asparagus]
[watchamacallit]
[a]
[abracadabra]
[abyss]
[ant]
13 words read from words.txt
a
[a] is a word
ab
[ab] is unknown
al
[al] is unknown
all
[all] is a word
alt
[alt] is unknown
alte
[alte] is unknown
alter
[alter] is a word
triceratops
[triceratops] is a word
brachiosaurus
[brachiosaurus] is a word
abys
[abys] is unknown
abbey
[abbey] is unknown
abyss
[abyss] is a word
ant
[ant] is a word
a
[a] is a word
archimedes
[archimedes] is a word
I just found this code online, and do not understand how the input should be formatted. An example of similar input from the same programmer is shown here: Pushdown automaton implemented in C
But it still does not help that much. Here is what it says:
The input format is like:
e01:e0$:000111:a:ad:aeeb$:b0eb0:b10ce:c10ce:ce$de The input is
separated by a semicolon “:”, first section is “input alphabet”,
second is “stack alphabet”, then “input” and the last whole bunch are
transition functions.
Can anyone provide some guidance how the input is handled? I am trying really hard for about 6 hours now, and cannot for the life of me decipher how the input should be formatted for this code.
Once it is compiled with gcc, to run it just do "./executable" and press enter. Then paste in the sample input string as shown above (although for this program I would need a different input).
/* This C file implements a Turing Machine
* author: Kevin Zhou
* Computer Science and Electronics
* University of Bristol
* Date: 21st April 2010
*/
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef struct tapes {
struct tapes *left;
struct tapes *right;
char content;
} Tape;
typedef enum { LEFT,RIGHT } Direction;
typedef struct transition {
char current_state;
char tape_symbol;
char new_state;
char new_tape_symbol;
Direction dir;
} Transition;
typedef struct list {
Transition *content;
struct list *next;
} List;
typedef struct tm {
char *input_alpha;
char *input;
char *tape_alpha;
char start;
char accept;
char reject;
List *transition;
} TM;
Tape *insert_tape(Tape *t, Direction dir, char c) {
Tape *head = t;
Tape *new1 = calloc(1,sizeof(Tape));;
new1 -> content = c;
if(dir == LEFT) {
while(t->left != NULL) {
t = t->left;
}
new1->right = t;
new1->left = NULL;
t->left = new1;
return new1;
}
if(dir == RIGHT) {
while(t->right != NULL) {
t = t->right;
}
new1->left = t;
new1->right = NULL;
t->right = new1;
}
return head;
}
Tape *create_tape(char *input) {
int i=1;
Tape *t = calloc(1,sizeof(Tape));
t->content = input[0];
while(1) {
if(input[i] == '\0') break;
t = insert_tape(t,RIGHT,input[i]);
i++;
}
return t;
}
/* turn the input string into Transition fields */
Transition *get_transition(char *s) {
Transition *t = calloc(1,sizeof(Transition));
Direction dir;
t->current_state = s[0];
t->tape_symbol = s[1];
t->new_state = s[2];
t->new_tape_symbol = s[3];
dir = (s[4]=='R')? RIGHT:LEFT;
t->dir = dir;
return t;
}
/* turn the string into transitions and add into list */
List *insert_list( List *l, char *elem ) {
List *t = calloc(1,sizeof(List));
List *head = l;
while(l->next!=NULL)
l = l->next;
t->content = get_transition(elem);
t->next = NULL;
l->next = t;
return head;
}
/* insert a transition into a list */
List *insert_list_transition( List *l, Transition *tr) {
List *t = calloc(1,sizeof(List));
List *head = l;
while(l->next!=NULL)
l = l->next;
t->content = tr;
t->next = NULL;
l->next = t;
return head;
}
void print_tape( Tape *t,char blank) {
char c;
while(1) {
if(t->content != blank) break;
t= t->right;
}
while(1) {
if(t==NULL) break;
c = t->content;
if(t->content != blank)
putchar(c);
t= t->right;
}
putchar('\n');
}
void print_transition (Transition *t) {
char s1[] = "Left";
char s2[] = "Right";
if(t==NULL) {
printf("NULL Transfer");
return;
}
printf("current:%c tape:%c new state:%c new tape:%c direction %s\n",t->current_state,t->tape_symbol,t->new_state,t->new_tape_symbol,(t->dir == LEFT)?s1:s2);
}
/*test if the char c is in the string s */
int contains ( char c, char *s ) {
int i=0;
while(1) {
if(c== s[i]) return 1;
if(s[i] == '\0') return 0;
i++;
}
}
/* test if the input is a valid input */
int is_valid_input( char *input_alpha, char *input ) {
int i=0;
char c;
while(1) {
c = input[i];
if(c == '\0') break;
if(!contains(c,input_alpha)) return 0;
i++;
}
return 1;
}
TM *createTM (char *input) {
TM *m = calloc(1,sizeof(TM));
List *tr = calloc(1,sizeof(List));
char *buffer;
/*read input alphabet of PDA*/
buffer = strtok(input,":");
if(buffer == NULL) {
printf("Error in reading input alphabet!\n");
exit(1);
}
m->input_alpha = buffer;
/*read tape alphabet*/
buffer = strtok(NULL,":");
if(buffer == NULL) {
printf("Error in reading tape alphabet!\n");
exit(1);
}
m->tape_alpha = buffer;
/*read input sequence*/
buffer = strtok(NULL,":");
if(buffer == NULL) {
printf("Error in reading input sequence!\n");
exit(1);
}
if(!is_valid_input(m->input_alpha,buffer)) {
printf("Error! Input contains some invalid characters that don't match the input alphabet!\n");
exit(1);
}
m->input = buffer;
buffer = strtok(NULL,":");
m->start = buffer[0];
buffer = strtok(NULL,":");
m->accept = buffer[0];
buffer = strtok(NULL,":");
m->reject = buffer[0];
/*read tape transition*/
while(1) {
buffer = strtok(NULL,":");
if(buffer == NULL) break;
tr = insert_list(tr,buffer);
}
m->transition = tr->next;
return m;
}
Transition *find_transition(List * list,char state, char tape_symbol) {
Transition *t;
while(1) {
if(list==NULL) return NULL;
t = list -> content;
if(t->current_state == state && t->tape_symbol == tape_symbol)
return t;
list = list->next;
}
}
Tape *move(Tape *t,Direction dir, char blank) {
if(dir == LEFT) {
if(t->left==NULL) {
t = insert_tape(t,LEFT,blank);
}
return t->left;
}
if(dir == RIGHT) {
if(t->right==NULL) {
t = insert_tape(t,RIGHT,blank);
}
return t->right;
}
return NULL;
}
void simulate( TM *m ) {
/* first symbol in input symbol used to represent the blank symbol */
const char blank = m->tape_alpha[0];
char current_state = m->start;
Tape *tape = create_tape(m->input);
Tape *current_tape = tape;
char current_tape_symbol;
Transition *current_transition;
while(1) {
if(current_state == m->accept) {
printf("Accept\n");
print_tape(tape,blank);
break;
}
if(current_state == m->reject) {
printf("Reject\n");
print_tape(tape,blank);
break;
}
current_tape_symbol = (current_tape==NULL||current_tape ->content == '\0')?blank:current_tape->content;
current_transition = find_transition(m->transition,current_state,current_tape_symbol);
current_state = current_transition -> new_state;
current_tape -> content = current_transition -> new_tape_symbol;
current_tape = move( current_tape, current_transition ->dir, blank);
}
}
int main(void) {
char s[300];
TM *p;
scanf("%s",s);
p = createTM(s);
simulate(p);
return 0;
}
The heavy use of the line buffer = strtok(NULL,":") confirms that the input strings are (like in the linked-to code) colon-delimited.
The struct defintions are the key to reverse-engineering the input.
The main struct is:
typedef struct tm {
char *input_alpha;
char *input;
char *tape_alpha;
char start;
char accept;
char reject;
List *transition;
} TM;
The function createTM() is the function which splits the input on : and loads the Turing machine. struct tm has 7 fields and createTM() has 7 clear phases
1) The first part is the input alphabet. Presumably this would be a string of 1 or more characters, e.g. 01.
2) The second part is the tape is the tape alphabet. The only character in this which plays any role in the rest of the code is the first character. The line const char blank = m->tape_alpha[0]; in the main simulation function indicates that the first character plays the role of the blank character -- the character which indicates that a tape square is empty. The ability to write the blank to a square allows the Turing machine to erase the data in a square. Note that in some sense this part of the input is out of order -- it is listed as the third field in the struct definition but is the second field in the input string.
3) The thirs part is the initial input on the tape. It is a string all of whose characters are drawn from the first part. The function is_valid_input() is used to check this condition.
4) The next part is the start state, which consists of a single char
5) The next part is the accept state, which is again a single char. Thus, in this model of a TM there is a single accepting state
6) The next part is the rejecting state, which is again represented by a single char
7) What follows is a sequence of strings, fed into a linked list of strings. The key function in understanding how it works is get_transition() which takes one of these transition strings and converts it into a Transition struct, declared as:
typedef struct transition {
char current_state;
char tape_symbol;
char new_state;
char new_tape_symbol;
Direction dir;
} Transition;
Looking carefully at the function get_transition() you can infer that a transition is represented by a string of length 5 where the last char is either R or L. An example would be something like a1b0R which says something like "if you are in state a while scanning symbol 0, transition to state b, write symbol 1 and the move to the right".
Putting it all together, the form of an input string would be something like:
01:_102:1001010101:$:a:r:$0b1R:b1b0L:a1b2R
corresponding to
01 _102 1001010101 $ a r $0b1R b1b0L a1b2R
input tape input start accept reject transitions
| alphabets | | states |
(blank = '_')
I just made some transitions at random, and neither know nor care what the program would do with this input. This should be enough for you to start experimenting with the program.
' I need to be able to create a alphabet tree. Then open an example .txt file with '.','-' and '/' '//'. '.' goes to the left of the tree or in this case the rist letters.'-'dash to the right.
http://www.skaut.ee/?jutt=10201 - what the tree looks like. '
#include <stdio.h>
#include<stdlib.h>
#include<string.h>
struct MorsePuu {
char t2ht;
struct MorsePuu *punkt, *kriips, *next;
};
static int i;
char TAHED[32]={' ','E','I','S','H','V','U','F','Ü','A','R','L','Ä','W','P','J','T','N','D','B','X','K','C','Y','M','G','Z','Q','O','Ö','™'};
//creating the "alphabet-tree"
struct MorsePuu *Ehitamine(int N) {
struct MorsePuu *uus;
int nl, nr;
if (N==0) {return NULL;}
else {
nl = N / 2;
nr = N-nl-1;
uus = malloc(sizeof *uus);
uus->t2ht = TAHED[i];
i++;
uus->punkt = NULL;
uus->kriips = NULL;
uus->punkt = Ehitamine(nl);
uus->kriips = Ehitamine(nr);
return uus;
}
}
//creating the order of the tree.
Preorder(struct MorsePuu *JViit) {
printf("%c",JViit->t2ht);
if (JViit->punkt != NULL) {
Preorder(JViit->punkt);}
// printf("%c",JViit->t2ht); Siin oleks Inorderi väljatrükk
if (JViit->kriips != NULL) {
Preorder(JViit->kriips);}
// printf("%c",JViit->t2ht); Ja siin oleks Postorderi väljatrükk
}
main(void) {
struct MorsePuu *morse, *abi;
char rida[128];
FILE *fm=NULL;
printf("Käigepealt tuleb morsepuu ?les ehitada!");
i = 0;
morse=Ehitamine(31);
printf("Puu väljatrükk preorder järjekorras.\n");
Preorder(morse);
printf("%c",morse);
//opening the file . Contents e.g .-/.// return ie. // stops it.
fm = fopen("morse1.txt", "r");
fgets(rida, 128, fm);
printf("\n %s", rida);
fclose(fm);
//this is where the reading and changing loop crashers.
/*
for(i=0; i<strlen(rida); i++){
if(rida[i]=='/'){
}
if(rida[i] == '.'){
//printf();
abi=abi->punkt;
}
if(rida[i]== '-'){
abi=abi->kriips;
}
}
*/
}
The problem starts from the last loop. The letter tree is created but i am not able to search the letter from the tree.
you didn't allocate any memory for *abi here
main(void) {
struct MorsePuu *morse, *abi;
char rida[128];
FILE *fm=NULL;
Abi is a pointer to struct MorsePuu, it points to a random location and when you use it later you cause undefined behaviour at line abi=abi->punkt.
You have to add a line
abi = malloc( sizeof( struct MorsePuu )) ;