c print char pointer that in main when value changed in function - c

main
...
char coords;
get_coords(1, &coords);
printf("{%s}", coords);
...
get_coords:
void get_coords(int num, char *coords){
if (num == 1){
*coords = '0-0';
}
}
problem seems to happen when the code tries to execute the printf and simply returns errors back... if i remove that line of code or change %s to %c it will work fine...

char coords;
printf("{%s}", coords);
coords is a char and not a string. %s conversion specification requires a char * argument and not a char. Passing an object of type char is undefined behavior.

%s is the format specifier for a C string. You're passing it a simple char.

What you want is probably something like this (please add the error checks yourself):
#include <stdio.h>
#include <string.h>
void get_coords(int num, char *coords)
{
if (num == 1) {
coords[0] = '0';
coords[1] = '-';
coords[2] = '0';
coords[3] = '\0';
}
}
int main(void)
{
char coords[4];
memset(coords, 0, sizeof(coords));
get_coords(1, coords);
printf("{%s}\n", coords);
return 0;
}

Related

search of string in an array of strings

i wrote some code that is supposed to find the location of a given string in an array of strings.
problem is- it doesn't give the location. it gives something else.
i understand that probably the problem has to do with the differences between the pointers that are involved- a previous version that dealt with finding the position of a letter in a word worked well.
after a lot of attempts to figure out where is the bug, i ask your help.
kindly, explain me what should be done.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int what (char * token);
main()
{
int i=0;
char string[]="jsr";
char *token;
token=&string[0];
i=what(token);
printf(" location of input is %d \n", i);
return 0;
}
int what (char * token)
{
int i=1;
char *typtbl[]={"mov",
"cmp",
"add",
"sub",
"not",
"clr",
"lea",
};
char * ptr;
ptr=(char *)typtbl;
while (!(strcmp(ptr,token)==0))
{
ptr=(char *)(typtbl+i);
i++;
}
return i;
}
As pointed out, you did not design function what properly. What value should it return if your search function go through all the pointers but does not find the desired string? Typically in that case return -1 would be a choice to indicate nothing found. Also in this case, using a for loop would probably be more suitable, you can just return the index immediately instead of going through all pointers.
int what(char *token)
{
char *typtbl[] = {
"mov",
"cmp",
"add",
"sub",
"not",
"clr",
"lea",
};
for( size_t i = 0; i < sizeof(typtbl)/sizeof(char*); ++i )
{
char *ptr = typtbl[i];
if(strcmp(ptr, token) == 0)
{
return i; // found something
}
}
return -1; // found nothing
}
A cleaner working version.
Main issue is in the (char *)(typtbl+i) replaced by typtbl[i] in the following code. typtbl+i is equivalent to &typtbl[i], so if my memory is good, it's a pointer on the pointer of the string and not the pointer of string itself
I added a NULL at the end of the array to be able to stop if the string is not present and return -1 to clearly say it was not found.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int what(char *token);
int main()
{
int i = 0;
char string[] = "jsr";
i = what(string);
printf(" location of input is %d \n", i);
return 0;
}
int what(char *token)
{
char *typtbl[] = {
"mov",
"cmp",
"add",
"jsr",
"not",
"clr",
"lea",
NULL
};
int i = 0;
while(typtbl[i] && !(strcmp(typtbl[i], token) == 0)) {
++i;
}
if(!typtbl[i])
i = -1;
return i;
}
char *token; token=&string[0]; was useless because string == &string[0].
A few things:
Your main function is missing its return type.
The while loop in what doesn't stop when the element isn't found. Therefore you are reading out of bounds.
This should do the work w/o pointer arithmetic.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int what (char * token);
int main(){
int i=0;
char string[]="jsr";
char *token;
token=&string[0];
i=what(token);
printf(" location of input is %d \n", i);
return 0;
}
int what (char * token){
unsigned int i=0;
char *typtbl[]={"mov",
"cmp",
"add",
"sub",
"not",
"clr",
"lea",
};
unsigned int typtbl_x_size = sizeof(typtbl)/sizeof(typtbl[0]);
char * ptr;
ptr=typtbl[i];
while (!(strcmp(ptr,token)==0)){
i += 1;
if (i >= typtbl_x_size){
printf("element not in list\n");
return -1;
}
ptr=typtbl[i];
}
return i;
}

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;
}

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);
}
}

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));
}

how can i write a function that returns a string in c?

When I try calling my function using printf(" %s",course_comment(1.0) );, the program crashes. This is my function:
char *course_comment(float b)
{
if(b < 2.0)
return("Retake");
}
Why does it crash? How can I fix it?
If your strings are constants and there is no intention to modify the result, working with string literals is the best choice, e.g.:
#include <stdio.h>
static const char RETAKE_STR[] = "Retake";
static const char DONT_RETAKE_STR[] = "Don't retake";
const char *
course_comment (float b)
{
return b < 2.0 ? RETAKE_STR : DONT_RETAKE_STR;
}
int main()
{
printf ("%s or... %s?\n",
course_comment (1.0),
course_comment (3.0));
return 0;
}
Otherwise, you can use strdup to clone the string (and don't forget to free it):
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char *
course_comment (float b)
{
char result[256];
if (b < 2.0)
{
snprintf (result, sizeof (result), "Retake %f", b);
}
else
{
snprintf (result, sizeof (result), "Do not retake %f", b);
}
return strdup (result);
}
int main()
{
char *comment;
comment = course_comment (1.0);
printf ("Result: %s\n", comment);
free (comment); // Don't forget to free the memory!
comment = course_comment (3.0);
printf ("Result: %s\n", comment);
free (comment); // Don't forget to free the memory!
return 0;
}
Depending on the order / structure of your program when 'course_comment' is first called - it maybe be undeclared & C will default its return type to an 'int'. Check for compiler warnings when you err.. compile.
Also make sure you understand about function prototypes, when & where they should be used (everywhere basically). I think the 'f' missing on the 1.0 means the argument will be auto cast to an int.
This works - not that I would ever do this:
#include <stdio.h>
const char *course_comment(float b); // <- fn prototype
int main(int argc, char *argv[]) {
printf(" %s",course_comment(1.0f));
}
const char *course_comment(float b)
{
if(b < 2.0)
return("Retake");
}
You should probably return a literal as const char * as they cannot be modified.
what does your function return if b is not less than 2.0?
what do you think would happen if you tried to use the return value?
Is your exact code what is crashing?
see this answer
As other said add an else with some return value ... And tell us exactly what the error is, please !
my2c
because your getting a NULL-pointer since 1.0 doesn't return anything.
Not your function crashes, printf crashes with:
printf(" %s", NULL);
Rule Of Thumb:
always have a defined return
gcc -Wall shows you all warnings
Return a pointer like that isn't particularly pretty. The least evil thing you can do is something like this:
main.c
#include "some_other_file.h"
int main()
{
printf(" %s", course_comment(1.0f) );
return 0;
}
some_other_file.h
#ifndef YADA_YADA_H
#define YADA_YADA_H
const char* course_comment(float b);
#endif
some_other_file.c
static const char COMMENT_RETAKE [] = "Retake";
const char* course_comment(float b)
{
const char* result;
if(b < 2.0f)
{
result = COMMENT_RETAKE;
}
else
{
result = ""; /* empty string */
}
return result;
}
Please note that you should use 1.0f notation when dealing with floats, and 1.0 notation when dealing with doubles. Otherwise the compiler will do silent promotions of your variables to double, and the code will turn slower.
If you want to return a string literal like return "blah", return type should be const char*.

Resources