How to implement puts() function? - c

I have tried to implement the puts function.It in actual returns a value but i cant get what should it return.please check my code and guide me further
/* implementation of puts function */
#include<stdio.h>
#include<conio.h>
void puts(string)
{
int i;
for(i=0; ;i++)
{
if(string[i]=='\0')
{
printf("\n");
break;
}
printf("%c",string[i]);
}
}

See comments in code.
int puts(const char *string)
{
int i = 0;
while(string[i]) //standard c idiom for looping through a null-terminated string
{
if( putchar(string[i]) == EOF) //if we got the EOF value from writing the char
{
return EOF;
}
i++;
}
if(putchar('\n') == EOF) //this will occur right after we quit due to the null terminated character.
{
return EOF;
}
return 1; //to meet spec.
}
And, as an aside - I've written the equivalent of putc, puts several different times in relation to developing on embedded systems. So it's not always just a learning exercise. :)
Comment on EOF: It is a POSIX constant from stdio.h.
In my Linux stdio.h, I have this definition:
/* End of file character.
Some things throughout the library rely on this being -1. */
#ifndef EOF
# define EOF (-1)
#endif
That definition code is GPL 2.1.

From the manual page:
#include <stdio.h>
int fputc(int c, FILE *stream);
int fputs(const char *s, FILE *stream);
int putc(int c, FILE *stream);
int putchar(int c);
int puts(const char *s);
Return Value
fputc(), putc() and putchar() return the character written as an unsigned char cast to an int or EOF on error.
puts() and fputs() return a non-negative number on success, or EOF on error.

Well, stdio's puts() returns a non-negative number on success, or EOF on error.

What's string supposed to be? You should define your function better, try:
void my_puts(const char *string)
instead of
void puts(string)
As noted in the link I included, you need to specify the data type of the argument you're passing (in your example string) and you cannot use the name of a function which has already been defined (i.e. puts ).

In addition to what has already been said, I am personally opposed to redefining standard library functions. However, if you absolutely must (e.g. for a homework assignment), and your compiler is complaining about conflicting types for 'puts', try putting this at the top:
#define puts _puts
#include <conio.h>
#include <stdio.h>
#undef puts

I don't see any point in implementing puts!
anyway, you should read the specs of puts so you can make it.
this may help
int myputs(char* s)
{
int x = printf("%s\n", s);
return (x > 0) ? x : EOF;
}
you should include stdio.h so you can use printf and EOF.
Note that this is not EXACT implementation of puts, because on error puts sets an error indicator and do some other stuff.
More details about puts, here.

Related

Strange behavior with fgetc() removing from a FILE stream

I have a very large program right now that I'm fairly certain that I should not publish publicly without getting into a lot of trouble so I'm going to try my best to explain the issue at hand.
I have 3 different functions, the names are different but the pointer names in the function match exactly, I'm not allowed to change the pointer names:
int function_1 (FILE \*in, FILE \* out, FILE \*changes);
int function_2(TYPEDEF STRUCT \*s, FILE \*in);
int function_3(TYPEDEF STRUCT \*s, FILE \*in);
My main function calls function_1 using function_1(stdin, stdout, changes) where changes is a pointer to a file stream that was opened in main.
In function1, I call function2(s,changes) and function_3(s,changes) in a loop. I also use fgetc(in) in function_1 after calling 2 and 3. I am failing in the first loop because I have a mismatch comparing characters between changes and stdin, when the are supposed to be the same.
For some strange reason, I find that by the time I get to the line int a=fgetc(in) in function_1, the stdin FILE stream has already lost two characters. If I add a line to fgetc(in) prior to calling function_2*,* I get the first letter in stdin and then my original int a=fgetc(in) shifts down one letter. Using this method, I determined that a character from stdin is lost after a call to function2 and another character from stdin is lost after function_3. However, I did not pass the *in pointer into those functions, I passed the *changes pointer.
I have never been more confused as to why this is happening, it doesn't make sense. If there was a problem with the fgetc(in) calls in the other two functions, it shouldn't only take off two characters as there are many of them in the other two functions, and those fgetc(in) calls are pulling the characters from the changes stream correctly.
Has anyone run into this before? Thanks in advance for any guidance.
edit:
I think this is as minimal of an example that I can get. I also just discovered that if I comment out the EOF If statement checks, I no longer lose the two characters.
#include <stdlib.h>
#include <stdio.h>
int next_struct(MYSTRUCT *s, FILE *in) {
int current_c = fgetc(in);
int eof_check= current_c;
if ((eof_check = getchar()) != EOF) {
//do stuff here
}
else {
return EOF;
}
//do more stuff
return 0;
}
int get_struct_c(MYSTRUCT *s, FILE *in) {
int c = fgetc(in);
int eof_check2= c;
if ((eof_check2=getchar()) != EOF) {
//do stuff
}
else {
return EOF;
}
return character;
}
int patch(FILE *in, FILE *out, FILE *diff) {
//intialize typedef struct
//create pointer to struct
while (!feof(diff)) {
if (next_struct(s,diff) == 0) {
//get charaters from diff and add to output
hunk_c = get_struct_c(s,diff);
read_c = fgetc(in);
fprintf(stderr, "%c\n", read_c);
}
return 0;
}

How do I properly call the function I created to the main?

So I suck with functions and need to debug this. Im pretty sure the function ToPigLating does its job well at converting. However I just need help calling the function ToPigLatin inside of my main function. But when I try doing that I just get a bunch of error codes.
#include <stdlib.h>
#include <string.h>
#define LEN 32
char* ToPigLatin(char* word[LEN]){
char word[LEN];
char translation [LEN];
char temp [LEN];
int i, j;
while ((scanf ("%s", word)) != '\0') {
strcpy (translation, word);
//just pretend I have all the work to convert it in here.
} // while
}
int main(){
printf("Enter 5 words: ");
scanf("%s", word);
ToPigLatin();
}```
Roughly, variables only exist within the function they're declared in. The word in ToPigLatin exists only within ToPigLatin. It is not available in main. This lets us write functions without worrying about all the rest of the code.
You need to declare a different variable in main, it can also be called word, to store the input and then pass that into ToPigLatin.
Let's illustrate with something simpler, a function which doubles its input.
int times_two(int number) {
return number * 2;
}
We need to give times_two a number.
int main() {
// This is different from "number" in times_two.
int number = 42;
// We have to pass its value into time_two.
int doubled = times_two(number);
printf("%d doubled is %d\n", number, doubled);
}
Your case is a bit more complicated because you're working with input and memory allocation and arrays. I'd suggest just focusing on arrays and function calls for now. No scanf. No strcpy.
For example, here's a function to print an array of words.
#include <stdio.h>
// Arrays in C don't store their size, the size must be given.
void printWords(const char *words[], size_t num_words) {
for( int i = 0; i < num_words; i++ ) {
printf("word[%d] is %s.\n", i, words[i]);
}
}
int main(){
// This "words" variable is distinct from the one in printWords.
const char *words[] = {"up", "down", "left", "right"};
// It must be passed into printWords along with its size.
printWords(words, 4);
}
ToPigLatingToPigLating function expects to have a parameter like ToPigLating("MyParameter");
Hello there icecolddash.
First things first, there are some concepts missing. In main section:
scanf("%s", word);
You're probably trying to read a string format and store in word variable.
In this case, you should have it on your declaration scope. After some adjustment, it will look like this:
int main(){
char word[LEN];
As you defined LEN with 32 bytes maximum, your program will not be allowed to read bigger strings.
You're also using standard input and output funcitions as printf, and so you should ever include stdio.h, thats the header which cointains those prototypes already declared, avoiding 'implicit declaration' compiling warnings.
Next issue is how you're declaring your translation function, so we have to think about it:
char* ToPigLatin(char* word[LEN])
In this case, what you wrote:
ToPigLatin is a funcion that returns a char pointer, which means you want your function to probably return a string. If it makes sense to you, no problem at all. Although we got some real problem with the parameter char* word[LEN].
Declaring your variable like this, assume that you're passing an array of strings as a parameter. If I got it right, you want to read all five words in main section and translate each one of them.
In this case I suggest some changes in main function, for example :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define LEN 32
#define MAX_WORDS 5
char *globalname = "translated";
char* ToPigLatin(char* word){
char *translation = NULL;
//Translation work here.
if ( !strcmp(word, "icecolddash") ){
return NULL;
}
translation = globalname;
return translation;
}
int main(){
char word[LEN];
char *translatedword;
int i;
printf("Enter 5 words: \n");
for ( i=0; i < MAX_WORDS; i++ ){
fgets(word, sizeof(word), stdin);
strtok(word, "\n"); // Just in case you're using a keyboard as input.
translatedword = ToPigLatin(word);
if ( translatedword != NULL ){
//Do something with your translation
//I'll just print it out as an example
printf("%s\n", translatedword);
continue;
}
// Generic couldn't translate message
printf("Sorry, I know nothing about %s\n", word);
}
return 0;
}
The above code translate every word in a fixed word "translated".
In case of reading the exact input "icecolddash", the program will output a generic error message, simulating some problem on translation process.
I hope this help you out with your studies.
There are a few things that I see.
#include <stdio.h>
#include <stdlib.h>
char* ToPigLatin(char* word){
printf(word);
return word;
}
int main(){
printf("Enter 5 words: ");
// declare the variable read into by scanf
char * word = NULL;
scanf("%s", word);
//Pass the variable into the function
ToPigLatin(word);
// Make sure you return an int from main()
return 0;
}
I left some comments in the code with some specific details.
However, the main thing that I would like to call out is the style of the way you're writing your code. Always try to write small, testable chunks and build your way up slowly. Try to get your code to compile. ALWAYS. If you can't run your code, you can't test it to figure out what you need to do.
As for the char ** comment you left on lewis's post, here is some reading you may find useful in building up your intuition:
https://www.tutorialspoint.com/what-does-dereferencing-a-pointer-mean-in-c-cplusplus
Happy coding!

C programming: Returning string from a function

I am tring to print compose a function can get the specific line from a file, like string=extract_line(2), then the string will be the content of the 2nd line of a file.
but when I tried to put the function in a head file, I got Segmentation fault.
Here is my code:
test.c:
#include "extract_line.h"
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char const *argv[])
{
extract_line(2);
extract_line(3);
printf("%s\n", str);
return 0;
}
extract_line.h
#include <stdio.h>
#include <stdlib.h>
#define TEMP_PATH "/home/pi/project/PCD_8544_screen/show_on_LCD/network_speed.txt"
static char str[256];
void extract_line( int Tgt_Line )
{
FILE *fp;
fp=fopen(TEMP_PATH, "r");
// char str[256];
char holder;
int line=0;
while((holder=fgetc(fp)) != EOF) {
if(holder == '\n') line++;
if(line == Tgt_Line) break; /* 1 because count start from 0,you know */
}
if(holder == EOF) {
printf("%s doesn't have the 2nd line\n", fp);
//error:there's no a 2nd
}
int i=0;
while((holder=fgetc(fp)) != EOF && (holder != '\n' )) {
// putchar(holder);
str[i] = holder;
i++;
}
// printf("%s\n",str);
fclose(fp);
// return str;
}
In the following line of code:
printf("%s doesn't have the 2nd line\n", fp);
You're printing a FILE * as though it's expected to point at a string (filename?). As printf expects a char *, this is likely to cause irrational behaviour. Note that your compiler is probably SCREAMING at you about this! Perhaps you meant:
printf("%s doesn't have the 2nd line\n", TEMP_PATH);
Additionally, there's a possibility for a null pointer dereference which would also cause irrational behaviour between the following two lines:
fp=fopen(TEMP_PATH, "r");
// snip! you need to check fp here!
while((holder=fgetc(fp)) != EOF) {
On that note, your loop is infinite on systems where char is an unsigned type, as EOF is negative which can't possibly compare equal to any unsigned values. As fgetc returns an int with an unsigned char within it and holder is a char, the downward conversion discards the information required for your loop to terminate. holder should be defined as an int, instead.
As there's no upper bound on how many characters are read set by your loop, it's possible that str may be accessed (and assigned) out of bounds in str[i] = holder;. This could cause irrational behaviour.
Additionally, it appears there's no explicit assignment of a '\0' string terminator. As str is defined with static storage duration (not to be confused with your static keyword, which provides internal linkage), that won't really cause irrational behaviour, in fact it's quite predictable, but your output might not be as you expect if the first call reads a line longer than the second call.
Finally, just a few nitpick notes:
I suggest using size_t rather than int for variables which are expected to count or refer to array elements (e.g. int i=0; should be size_t i=0;). This is to make it explicit that negative numbers aren't acceptable, which might also speed your code up a little.
It's a little bit strange to put code in header files. Usually definitions only go into header files, which we #include, and code goes into code files, which we link to (e.g. gcc -o x.c compiles x.c, then gcc main.c x.o compiles main.c and links it with x.o).
You need to have a main() function or you need to run the script from within any other function..
#include "extract_line.h"
#include <stdio.h>
#include <stdlib.h>
void main() {
extract_line(2);
extract_line(3);
printf("%s\n", str);
}

Implementing getchar with read

I was trying to implement getchar() function using read() in unistd.h.
Since system calls are pricy, I wanted to execute less read() functions as possible.
If I use "getchar", it works fine. However, "mygetchar" does not work in this case.
Can anyone point out what I have done wrong below?
#include <stdio.h>
#include <unistd.h>
#define BUF_SIZE 1024
int startIndex;
int endIndex;
int mygetchar(void){
char buffer[BUF_SIZE];
startIndex=0;
endIndex=0;
if(startIndex == endIndex){
int r;
r = read(0,buffer,BUF_SIZE);
startIndex=0;
endIndex=r;
}
return buffer[startIndex++];
}
int main(){
char c;
int i=0;
do{
c = mygetchar();
putchar(c);
i++;
}
while(c != EOF);
return 0;
}
Think carefully about your buffer. What happens to the buffer when the function call ends? It goes away.
This means that for 1023 out of 1024 calls, your buffer is unitialized and your offsets are pointing into nonsensical data.
Basically you need a global variable for the buffer too:
static char buf[BUF_SIZE];
static size_t bufCur = 0;
static size_t bufEnd = 0;
int mygetchar(void)
{
// ...
}
(Note that the static is pretty much pointless when your code is all in one file. If you were to pull your mygetchar into a header and implementation file though, you would want to use a static global so as to keep it from being linkable from outside of the same compilation unit.)
(Fun fact: the 0s for bufCur and bufEnd actually can be left implicit. For clarity, I would put them, but the standard dictates that they are to be zero-initialized.
As Jonathan Leffler pointed out, unless you plan on using the buffer elsewhere (and I don't know where that would be), there's no need for a global. You can just use a static variable inside of the function:
void mygetchar(void)
{
static buf[BUF_SIZE];
static size_t bufCur = 0;
static size_t bufEnd = 0;
// ...
}

C functions without header files

This should be very trivial. I was running through a very basic C program for comparing strings:
#include <stdio.h>
int strcmp(char *s, char *t);
int main()
{
printf("Returned: %d\n", strcmp("abc", "adf"));
return 0;
}
int strcmp(char *s, char *t)
{
printf("Blah\n");
while (*s++ == *t++)
{
if (*s == '\0')
return 0;
}
return *s - *t;
}
So I've basically implemented my own version of the strcmp function already present in string.h. When I run the above code, I only see return values of 0, 1, or -1 (at least for my small set of test cases) instead of the actual expected results. Now I do realize that this is because the code doesn't go to my implemented version of strcmp, but instead uses the string.h version of the function, but I'm confused as to why this is the case even when I haven't included the appropriate header file.
Also, seeing how it does use the header file version, shouldn't I be getting a 'multiple implementations' error (or something along those lines) when compiling the code?
You're using gcc, right? gcc implements some functions as built-ins in the compiler and it seems that strcmp is one of those. Try compiling your file with the -fno-builtin switch.
Header files just tell the compiler that certain symbols, macros, and types exist. Including or not including a header file won't have any effect on where functions come from, that's the linker's job. If gcc was pulling strcmp out of libc then you probably would see a warning.
Not as elegant as the earlier answers, another way to get this done
#include <stdio.h>
static int strcmp(char *s, char *t); /* static makes it bind to file local sym */
int main()
{
printf("Returned: %d\n", strcmp("abc", "adf"));
return 0;
}
int strcmp(char *s, char *t)
{
printf("Blah\n");
while (*s++ == *t++)
{
if (*s == '\0')
return 0;
}
return *s - *t;
}
Without knowing what compiler and lib. version you use, all conclusion are only 'possibility'. So the most reasonable thing that stdio.h already includes stdlib.h or string.h
strcmp is the name of a standard library function. As such you are only permitted to declare the function (although you must use a correct declaration); you are not permitted to provide another definition for it. The implementation can assume that whenever you use strcmp you are referring to the standard library function even if you haven't used the correct #include for it.
If you want to provide an alternative strcmp then you should give it an alternative name.

Resources