How access with recursion to some element of a struct - c

I would write a function , that elaborates a struct and return the length of an array of character ,that is define in the same struct, in a recursive way.
The struct is:
typedef struct BinSeq {
char* data;
int dimension;
}BinSeq
data, the array of character,can have only two type of character: '0' and '1',while dimension is the length of array, but not of sequence of '0' and '1'.
So I try to write this function:
int length(BinSeq* bin_seq) {
int i;
if(bin_seq->data[i] == '0' || bin_seq->data[i] == '1')
{
i++;
return 1 + length(bin_seq->data[i]);
}else
return 0;
}
but I have may doubts about this. First caused by the compiler that says:
warning: passing argument 1 of ‘length’ makes pointer from integer without a cast [enabled by default]
return 1 + length(bin_seq->data[i]);
^
recursion.c:13:6: note: expected ‘struct BinSeq *’ but argument is of type ‘char’
int length(BinSeq* bin_seq) {
How can I work on the data , If I had to pass to my function the Binseq* bin_seq? I know that my code is in error for this , but if I want calculate the leght I had to increment the variable i, but the it won't , I think, increase. How can I work on this?

like this:
#include <stdio.h>
typedef struct BinSeq {
char *data;
int dimension;
} BinSeq;
int length(BinSeq* bin_seq) {
if(*bin_seq->data == '0' || *bin_seq->data == '1')
return 1 + length(&(BinSeq){bin_seq->data + 1, bin_seq->dimension});
return 0;
}
int main(int argc, char** argv) {
BinSeq binary;
binary.data = "0000110111";
binary.dimension = 2014;
int dimension_of_array = length(&binary);
printf("%d\n", dimension_of_array);
return 0;
}
by using the auxiliary recursive function
int aux_length(const char *data){
if(*data == '0' || *data == '1')
return 1 + aux_length(data + 1);
return 0;
}
int length(BinSeq* bin_seq) {
return aux_length(bin_seq->data);
}

If I interpreted correctly, this code should do what you want:
int length(BinSeq* bin_seq, int i) {
if(bin_seq->data[i] == '0' || bin_seq->data[i] == '1')
{
return 1 + length(bin_seq->data, ++i);
} else {
return 0;
}
}
Although there are more efficient ways to code this: in practice you can simply use pointer arithmetic to loop over the char array until you find anything but a 0 or 1. You have also not shown how you initialize the sequence; one would assume it is done correctly with a known terminator character (e.g. \0).

I had to write a function int length(BinSeq* bin_seq)that calculates recursively the length of the binary sequence bin_seq. The struct is:
typedef struct BinSeq {
char* data;
int dimension;
}BinSeq
and the main is:
int main(int argc, char** argv) {
Binseq* binary;
binary.data = "0000110111";
binary.dimension = 2014;
int dimension_of_array = length(BinSeq* bin_seq);
}
How can I calculate the length of data, if I had to pass bin_seq to function?

Related

Undefined reference to `startswith'

I am writing some C in which the program is going to convert the first command line argument into a int and check to see if it is an int. If it isnt a integer value it will then attempt to check to see whether the string begins with a '.' character or not. For some reason I am getting an undefined reference. How is this an undefined reference when it seems to be defined?
Here is the following code:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <ctype.h>
#include <string.h>
int startswith(char,char);
int main(int argc, char * argv[]) {
int forst;
srand(time(NULL));
int speed_delay = rand() % 20;
printf("The speed delay is:%i\n", speed_delay);
int first = atoi(argv[1]);
printf("First:%i\n", first);
if (first == 0) {
//this means text was inserted instead of a number
if (startswith(first, '.')) {
printf("string starts with a period !");
}
} else {
}
int startswith(const char * one,
const char * two) {
if (strncmp(one, two, strlen(two)) == 0) {
return 1;
}
return 0;
}
}
Your declaration and definition of startswith are incompatible.
The declaration has two parameters of type char, but the function actually has two parameters of type const char *.
You also defined startswith inside of main. Functions cannot be nested.
Because no function exists that matches the declaration, you have an undefined reference.
Fix your declaration to match the definition.
int startswith( const char *, const char *);
You're also not calling this function correctly. You pass in an int and a char. It should be called like this:
if(startswith(argv[1],"."))
Try replacing int startswith(char,char); with below
static inline const char *startwith(const char *s, const char *prefix)
{
size_t sz = prefix ? strlen(prefix) : 0;
if(s && sz && strncmp(s, prefix, sz) == 0){
return s+sz;
}
return NULL;
}

incompatible pointer compiler error

I have this assignment where we expected to write a program that takes
a positive integer number as a command line argument and prints the
smallest prime number bigger than the given number.
The main function shouldn't be edited, however, you may create a
header file for defining needed functions.
So far this is what I came up with, I just can't find out what
is wrong with my program. Help is appreciated.
main function: I can't edit the main function, however, you can create a header
#include "slow-prime.h"
int main(int argc, char *argv[]) {
int num;
int nxt;enter code here
int ret = EXIT_FAILURE;
if (argc < 2) {
printf("error: missing command line argument\n");
goto ERROR;
if (get_number(argv[1], &num)) {
printf("error: %s not a number\n", argv[1]);
goto ERROR;
}
next_prime(num, &nxt);
printf("%d\n", nxt);
ret = EXIT_SUCCESS;
ERROR:
return ret;
}
}
needed functions are created in the slow-prime.h
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// define true and false
#define true 1
#define false 0
// check whether the numer is prime or mnot
int isPrime(int num){
if (num < 2) {
return false;
}
for (int i = 2; i <= num / i; i++) {
if (num % i == 0) {
return false;
}
}
return true;
}
// get number
void get_number(char *argv[], int num) {
num = atoi(argv[1]);
}
// loop through the numbers/ and pick the one
void next_prime(int num, int next){
for(int i = 2; i < 80; i++){
if (isPrime(i) == true){
next = i;
if (next > num) {
return exit(0);
}
}
}
}
Error Message:
error
You have:
void get_number(char *argv[], int num) {
and you are calling the function using:
if (get_number(argv[1], &num)) {
You are passing the wrong types for both arguments.
argv[1] is of type char*.
&num is of type int*.
I think you should to use:
void get_number(char *arg, int *num) {
and change the implementation slightly.
void get_number(char *arg, int *num) {
*num = atoi(arg);
}
Also, given that get_number returns void, you cannot use it in the conditional of an if statement. You'll need to change its return type to something else, an int perhaps. In that case, using atoi might not be appropriate. atoi returns 0 when it cannot convert the string to an int. If 0 a valid value for you, then atoi is not a good choice. However, you can use sprintffor all cases.
If 0 is not a valid number, you can use:
int get_number(char *arg, int *num) {
*num = atoi(arg);
return *num;
}
If 0 is a valid number, you can use:
int get_number(char *arg, int *num) {
return (sprintf(arg, "%d", num) == 1);
}

Coding printf with array of function pointers

I am trying to code the printf function. The problem is that my code is getting very messy and I need some help to try to make it organized and working (hopefully). I have been told that I should use "array of function pointers" so I tried below (ft_print_it) as you can see but I do not know how to how to structure my code so that I can use a big array of function pointer to put every function like int_decimal_octal and friends. Can you help me on that? Where can I call them from?
Also, I realized the little function below (cast_in_short) is giving me the same result as printf if I write the output with my ft_putnbr. My second question is thus: Can I make my printf work with little functions like this? Thank you so much.
int cast_in_short(int truc)
{
truc = (short)truc;
return (truc);
}
/*
here in the main I noticed that I get the same behaviour
between my putnbr and printf thanks to my little function
cast_in_short. This is the kind of function I want to use
and put into an array of pointer of functions in order
to make my printf work
*/
int main()
{
int n = 32769;
n = cast_in_short(n);
ft_putnbr(n);
printf("\n");
return (0);
}
/* function to launch ft_print_it */
int ft_print_str_spec(va_list ap, char *flag)
{
if (ft_strlen(flag) == 1)
ft_putstr(va_arg(ap, char *));
else
{
ft_nbzero(ap, flag, 0);
ft_putstr(va_arg(ap, char *));
}
return (1);
}
int ft_print_oct(va_list ap, char *flag)
{
if (ft_strlen(flag) == 1)
ft_putnbr(decimal_octal((va_arg(ap, int))));
else
{
ft_nbzero(ap, flag, 1);
ft_putnbr(decimal_octal((va_arg(ap, int))));
}
return (1);
}
#include "libft.h"
#include <stdarg.h>
#include <stdio.h>
char *ft_strjoin2(char const *s1, char const c);
#include "libft.h"
#include <stdarg.h>
#include <stdio.h>
int decimal_octal(int n) /* Function to convert decimal to octal */
{
int rem;
int i;
int octal;
i = 1;
octal = 0;
while (n != 0)
{
rem = n % 8;
n /= 8;
octal += rem * i;
i *= 10;
}
return (octal);
}
I think the best way to organize your code to avoid the function like your "flag_code" is to use an array of structure. With structure that contain a char (corresponding to the flag) and a function pointer.
For example :
typedef struct fptr
{
char op;
int (*ptr)(va_list);
} fptr;
And instatiate it like that (with { 'flag', name of the corresponding function} ) :
fptr fptrs[]=
{
{ 's', ft_print_nb_spec },
{ 'S', ft_print_nb_up },
{ 0, NULL }
};
Then when you know have char after the % (the flag) you can do something like this :
int i = -1;
while (fptrs[++i].op != flag && fptrs[i].op != 0);
if (fptrs[i].op != 0)
{
fptrs[i].ptr();
}
For exemple if flag = 'S' the while loop will stop when i = 1 and when you call fptrs[1].ptr() you will call the corresponding function in the structure.
I think instead of making your code messy by using function pointers, because in the end you cannot specialize printf function without providing the format, in C there is no function overloading or template functions. My suggestion is to special printf function by type.
// print seperator
void p (int end)
{ printf(end?"\n":" "); }
// print decimal
void pi (long long n)
{ printf("%lld",n); }
// print unsigned
void pu (unsigned long long n)
{ printf("%llu",n); }
// print floating point
void pf (double n)
{ printf("%g",n); }
// print char
void pc (char n)
{ printf("%c",n); }
// print string
void ps (char* n)
{ printf("%s",n); }
Test try here
pi(999),p(0),pf(3.16),p(0),ps("test"),p(1);
Output
999 3.16 test
Another option
In theory you can define polymorphic print function in a struct, in case you can do something like this. I haven't tested this yet.
struct Node
{
enum NodeType {Long,Double,Char,String} type;
union {long l,double d,char c,char* s};
};
void p(Node* n)
{
switch (n->type)
{
case Node::NodeType::Long: printf("%ld", n->l);
case Node::NodeType::Double: printf("%g",n->d);
case Node::NodeType::Char: printf("%c",n->c);
case Node::NodeType::String: printf("%s",n->s);
}
}

C - Errors when trying to make a hashtable

I'm working on a hash table that stores strings in linked lists so I can avoid collisions. However, I'm getting two errors that I'm not sure how to fix. The first error I am getting is in the line that says NewT->Table[i] == NULL;. It's saying warning: statement with no effects [-Wunused-value].
The second error I'm getting is in the same function. The error is in the line return NewT and the error is warning: return from incompatible pointer type[enabled by default]. I've been staring at this for awhile and I can't see where there is an unused value and I have no idea what the return error means even after a bit of research. Can someone explain these to me and help me fix them?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define HASH_MULTIPLIER 65599
/*Structures*/
typedef struct List_T
{
char *str;
int count;
struct List_T *next;
} ListT;
typedef struct Hash_T
{
int htsize;
ListT **Table;
} HashT;
/*Prototypes*/
unsigned int hash(const char *str);
HashT **ht_create(void);
int htsize;
int main(int argc, char *argv[])
{
if (argc <= 1)
{
printf("Please declare a table size");
return 1;
}
htsize = atoi(argv[1]);
return 0;
}
unsigned int hash(const char *str)
{
int i;
unsigned int h = 0U;
for (i = 0; str[i] != '\0'; i++)
h = h * HASH_MULTIPLIER + (unsigned char) str[i];
return h % htsize;
}
HashT **ht_create(void)
{
HashT *NewT;
int i;
if (htsize < 1) //invalid size for
{
fprintf(stderr,"Invalid Size for table");
exit(0);
}
if ((NewT = malloc(sizeof(HashT))) == NULL)
{
fprintf(stderr,"Invalid size for table");
exit(0);
}
if ((NewT->Table = malloc(sizeof(ListT *) * htsize)) == NULL)
{
fprintf(stderr,"Invalid size for table");
exit(0);
}
for (i = 0; i<htsize; i++)
{
NewT->Table[i] == NULL;
}
NewT->htsize = htsize;
return NewT;
}
The first error I am getting is in the line that says NewT->Table[i]
== NULL;. It's saying warning: statement with no effects [-Wunused-value].
This error shows up because the code is making a comparison and not an assignment. The value returned by the comparison (is Table[i] null?) is itself not assigned to anything else, which means it's unused.
Keep a single = operator instead of the doubled == to make sure you're actually assigning instead of comparing.
The second error I'm getting is in the same function. The error is in
the line return NewT and the error is warning: return from
incompatible pointer type[enabled by default].
Your function claims to be returning a pointer to a pointer to HashT, or HashT **, but you end up returning a pointer to HashT, or HashT * instead, which is the type of your NewT variable.
Your function's signature should use a single * instead of two.

Segmentation Fault in C

My code is giving me a segmentation fault and I can't seem to find what I'm doing wrong:
#include <stdio.h>
#include <string.h>
char find(char name[], char allNames[][10], int length)
{
int i=0;
for (i = 0; i < length; i++) {
if (strcmp(allNames[i],name) == 1) {
printf("%i",i);
return *name;
}
}
return -1;
}
main(){
char allNames[][10] = {"cat","dog","frog","log","bog"};
char name[] = "log";
int length=5;
printf("%s",find(name,allNames,length));
}
I'm really keen to understand all the mechanisms happening here and what I'm doing wrong for tomorrows exam. Thanks for your help!
EDIT: Really Appreciate the answers and information guys! I'm really quite new to C and just getting used to what every thing means. The particular exam question I am looking at is :
(a) The following function is intended to find the string name in the array
allNames. If found, it returns the position of name in the array. If not
found, it returns -1. Modify the code so that it works correctly.
int find(char name[], char allNames[][10])
{
for (i = 0; i < 10; i++) {
if (allNames[i] == name) {
return name;
}
}
return -1;
}
And I'm trying to get a program to work within these parameters. Cheers :)
http://coliru.stacked-crooked.com/a/d400c9a56d732446
#include <stdio.h>
#include <string.h>
char* find(char name[], char allNames[][10], int length)
{
int i=0;
for (i = 0; i < length; i++) {
if (!strcmp(allNames[i],name)) {
printf("%i",i);
return name;
}
}
return NULL;
}
int main(){
char allNames[][10] = {"cat","dog","frog","log","bog"};
char name[] = "log";
int length=5;
printf("%s",find(name,allNames,length));
}
Returning a single char will do you no good if you're trying to return a string. I would also suggest that you return a NULL if you cannot find the string.
Also, include the int before main; this is better style.
The direct reason for your Segmentation Fault here is because the code tried to print the char type with %s(which needs an address value).
void main()
{
char c = 'a';
printf("%s", c); // will cause Segmentation fault here
}
Back to your code, that is
char find(char name[], char allNames[][10], int length)//return char
printf("%s",find(name,allNames,length));
The minimal change to make it work as follows,
1) To return char*
char* find(char name[], char allNames[][10], int length)//return char*
{
int i=0;
for (i = 0; i < length; i++) {
if (strcmp(allNames[i],name) == 0) { // here should 0
printf("%i",i);
return name; // change name* to name
}
}
return NULL; // change to NULL
}
//to print
printf("%s",find(name,allNames,length));
2) to return position value
int find(char name[], char allNames[][10])
{
for (i = 0; i < 10; i++) {
if (allNames[i] == name) {
return i; // here, change to return i
}
}
return -1;
}
//then, you can print like this
printf("find at position: %d",find(name,allNames,length));
//or to print string by
int pos = find(name,allNames,length);
if(pos >= 0)
printf("find the string: %s",allNames[pos]);
This code is wrong on several levels.
gcc -Wall -Wextra reveals:
meh.c:15:1: warning: return type defaults to ‘int’ [-Wreturn-type]
main(){
^
meh.c: In function ‘main’:
meh.c:19:3: warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘int’ [-Wformat=]
printf("%s",find(name,allNames,length));
^
meh.c:21:1: warning: control reaches end of non-void function [-Wreturn-type]
}
^
What's up with that? Do you compile with warnings enabled?
I am ignoring the lack of indentation.
#include <stdio.h>
#include <string.h>
char find(char name[], char allNames[][10], int length)
What? How about: char *name, **list, int size)
{
int i=0;
Why set it to 0 here?
for (i = 0; i < length; i++) {
if (strcmp(allNames[i],name) == 1) {
printf("%i",i);
return *name;
Have you read strcmp's manpage? It returns ZERO when a string matches, so this code makes no sense.
*name is of type char, but you don't want to return a char. You want to return a pointer, no?
}
}
return -1;
Well, given that you feed that into %s in printf, what do you expect to hapen here? Normally one would return NULL.
}
main(){
This is obsolete syntax, I don't know where you stole it from. Use 'int main(void)'.
char allNames[][10] = {"cat","dog","frog","log","bog"};
Normally people just return such arrays with a NULL pointer, so that these can be iterated over and there is no need to pass anything about the size.
char name[] = "log";
Why not char *name = "log".
int length=5;
Incorrect. It hardcodes the amount of stored strings in allNames table.
printf("%s",find(name,allNames,length));
}

Resources