I want a user defined function which is equivalent to strlen() function in C. In the below program it does the same function as strlen() but it has a limit to it. How can I make it count any length of text.
#include <stdio.h>
#include <conio.h>
void main()
{
int len(char *);
char s[20];
int l;
printf("Enter a string: ");
gets(s);
l=len(s);
printf("length of string is =%d",l);
getch();
}
int len(char *t)
{
int count=0;
while(*t!='\0')
{
count++;
t++;
}
return(count);
}
I think your "limit" is because you use gets() on a buffer of 20 bytes. You will experience issues due to a buffer overflow. Exactly what happens when you do that is not entirely predictable.
If you fix that, I think your function will work as you expect it to. (Read the other people's answers for insight on your length function.)
If you truly want "any length", you'll need an arbitrary-precision integer library (such as libgmp) for the counter. That's pretty unreasonable, though, since the string will have to fit into your memory, and each character actually has to have an address. That is to say, the length of any string that fits into addressable space can be expressed in a variable of type size_t (or unsigned long int, I suppose; it'll be something of the same size as the machine's register size).
(Please don't ask about how to form the one-past-the-end pointer of a string that fills out the entire addressable memory.)
Its limit is int bounds. if you increase it, use long. Also, make it unsigned to double the maximum. If you want to be sure that it fit, use size_t (which original strlen use)
BTW, never use gets.
What's the limit you want? Historically a string is terminated by '\0' because its the only way to know where the string ends, otherwise you could actually read the whole stack or heap way past the true length of the string. A method used by other functions to identify the end of a string, to prevent crash not as a feature is to stop reading when a value outside the charset is found.
Edit:
Obviously I misunderstood the question.
int main(){
int Length = 0;
char StrArray[10] = "Hello";
while (StrArray[Length] != '\0')
{
StrArray[Length];
Length++;
}
std::cout << Length;
std::cin.get();
}
Related
How can I convert double to char*.
#include <stdio.h>
int main() {
char * buf;
double number = 3.123;
sprintf(buf,"%f",number);
printf("%s",buf);
return 0;
}
This method is does not want to work and I cannot know why.
char* buf declares buf as a character pointer, but does not actually allocate any memory for it. You should declare buf as an array to allocate memory:
char buf[128];
double number = 3.123;
sprintf(buf, "%f", number);
What you probably want is a floating-point to string conversion. What you need is not a char*, but rather an array. The difference is that an array allocates some space for the string, while a pointer is supposed to point to an already existing string, but there is no such string in your code.
Because of this, your code is producing Undefined Behavior (or UB for short), because sprintf() is attempting to write at the address that the buf pointer references. The pointer was not assigned to point to anything, so it is an uninitialized (wild) pointer. This pointer probably contains a random non-sense value and sprintf() is trying to write to it - it won't work, or even worse, will appear to work until you find a problem in a totally different part of the code.
Here is how you should do it:
#include <stdio.h>
int main(void)
{
char buf[100];
double number = 3.123;
sprintf(buf, "%f", number);
printf("%s", buf);
}
First we declare a character array. It can be any length, but for simplicity I chose 100. We can then use this array in a similar way, by writing to it using sprintf().
Now, there may be another problem. It won't show up in this small piece of code, but if you use sprintf() a lot you will notice a lot of bugs if you don't pay attention to the length of the array. The array has only 100 characters, but sprintf() doesn't know that! The function will simply attempt to write past the end of the array, a bug which is called a buffer overflow, yet another case of UB, and also a very common exploit for malicious attacks.
To ease the programmer's life, C has another function that is safer, snprintf(), which works pretty much the same but takes an extra parameter, the maximum length of the array. Here is how it works:
#include <stdio.h>
int main(void)
{
char buf[100];
double number = 3.123;
snprintf(buf, 100, "%f", number);
printf("%s", buf);
}
Even if we tried to write more than 100 characters to the buffer, the function would only write 100 (actually, 99 and a null terminator), and will discard the rest of the contents. This means that, if you pass the correct value for the length of the array, a buffer overflow won't occur.
when I run this code I always found a problem in my IDE. Can you give this solution ?
#include<stdio.h>
#include<string.h>
int main(void)
{
char cname[4]="mahe";
strcat(cname, "Karim");
printf("%s",cname);
getch();
return 0;
}
Your array isn't big enough. The original array isn't big enough to hold the null byte at the end of its initial value, so strcat() can't find the end of the string. And then you're adding to it, which writes outside the array. These are both causing undefined behavior.
It needs to be declared large enough to hold the original string, the string you're adding to it, and the trailing null byte. So it has to be at least 10 bytes (4+5+1).
char cname[10] = "mahe";
strcat(cname, "Karim");
printf("%s\n", cname);
Change char cname[4] to char cname[10]. Because you are setting the size 4 and so, you can't append any more to it after adding 4 chars initially.
So, change the size. That's it
I am having a problem with loop, I don't know why but loop never ends.
int main(int argc, char *argv[])
{
int j;
char s[2];
for(j=1;j<=3;j++)
{
sprintf(s,"s%d",j);
printf("%s", s);
}
system("PAUSE");
return 0;
}
I think loop should show s1s2s3 in console.
char s[2]; should be char s[3];, or else you will get a buffer overflow.
Abhineet explains why the change is necessary. However, in order to corroborate his answer, here is the relevant section from the standard.
7.19.6.6
The sprintf function is equivalent to fprintf, except that the output
is written into an array (specified by the argument s) rather than to a
stream. A null character is written at the end of the characters
written; it is not counted as part of the returned value. If copying
takes place between objects that overlap, the behavior is undefined.
From the documentation,
The size of the buffer should be large enough to contain the entire resulting string.
You are already pushing two chars to s, so, there is not enough space for appending \0. This will cause undefined behavior. The solution is to provide one extra char memory to append \0.
char s[2]; to char s[3];
I know I have replied pretty late but couldn't stop myself from explaining the OP, "why he has to use s[3] instead of s[2] ?"
I have two .c files that I would like to compile into on executable. Having just started learning C, I'm finding it tricky to know how to transfer text as an argument between functions (which I've found to be incredibly simple in every other language).
Here are the two files:
Program.c
#include <stdio.h>
#include <string.h>
int main(){
char temp[40] = stringCall();
printf("%s",temp);
}
StringReturn.c
#include <stdio.h>
#include <string.h>
char[] stringCall(){
char toReturn[40] = "Hello, Stack Overflow!";
return toReturn;
}
I usually get a problem that says something like "Segmentation Failed (core dumped)" or alike. I've done a lot of Googling and amazing I can't really find a solution, and certainly no simple tutorial "This is how to move text between functions".
Any help would be appreciated :)
char toReturn[40] = "Hello, Stack Overflow!";
return toReturn;
This is invalid, you're returning an auto array which gets out of scope after the function returns - this invokes undefined behavior. Try returning the string literal itself (it's valid throughout the program):
return "Hello, Stack Overflow!";
Or a dynamic duplicate of your array:
char toReturn[40] = "Hello, Stack Overflow!";
return strdup(toReturn);
In this latter case, you'll need to free() the string in the caller function.
You are correct, this isn't simple in C because C can't treat strings as values.
The most flexible way to do it is this:
// Program.c
char temp[40];
if (stringCall(temp, sizeof temp) <= sizeof temp) {
puts(temp);
} else {
// error-handling
puts("My buffer wasn't big enough");
}
// StringReturn.c
int stringCall(char *buf, int size) {
const char toReturn[] = "Hello, Stack Overflow!";
if (sizeof toReturn <= size) {
strcpy(buf, toReturn);
}
return sizeof toReturn;
}
stringCall doesn't return the string data, it writes it to a buffer supplied by the caller
A buffer always comes with a size. You could use size_t or ssize_t for this rather than int.
stringCall checks the size before writing. There are other ways to do this in a single call, all of which are either not in C89 and C99, or are defective in some other way. C11 introduces strcpy_s. Use what tools you can, which should be logically equivalent to checking it yourself as in my code above. Never forget to make sure there's space for the nul terminator, which invisibly lurks at the end of every C string.
stringCall returns the number of bytes that it wants to write, even if it doesn't write anything. This means that a caller whose buffer is too small can allocate a bigger one and try again. For that matter a caller can do stringCall(NULL, 0) to get the size without trying any particular buffer.
I'm using sizeof here because I'm using arrays whose size is known by the compiler, but in practice stringCall might use strlen or some other way of knowing how much data it wants to write.
As I've written it, callers are required not to pass in a negative value for size. That's usually OK, because their buffer in point of fact cannot have a negative size, so their code is already buggy if they do. But if you want to be really sure, or if you want to help your callers catch those bugs, you could write if ((int) sizeof toReturn < size) or if (size > 0 && sizeof toReturn < size).
"Most flexible" isn't always best, but this is good when the function is actually generating the text on the fly, especially when there isn't an easy way for the caller to know the length in advance without doing half the work that stringCall is supposed to do for them. The interface is similar to the C99 standard function snprintf.
Greetings,
I had been studying C++ for a while now.
I'm getting in to pointers now.
But I'm creating a program on C++ that will ask for a string("%s") input.
And I want to display its character on a different line.
But when I run the program I get the wrong letters.
Here's my code;
#include<stdio.h>
#include<stdlib.h>
main() {
char* name;
name = (char *)malloc(sizeof(char));
printf("Enter string: "); scanf("%s", name);
while(*name != '\0') {
printf("%c", name); *name++
}
}
Your reply is highly appreciated.
malloc(sizeof(char)) allocates space for a single character. This is probably not what you want. As the comments below point out, the dereferencing in *name++ is pointless. It does no harm, but perhaps indicates that you're thinking incorrectly about something. name++ has the same effect.
First, if you are going to study C++, you should learn to write C++ programs, not C programs. Here is your program in idiomatic C++:
#include <iostream>
#include <string>
int main(int, char **) {
std::string name;
std::cout << "Enter string: " << std::flush;
std::cin >> name;
std::cout << name << "\n";
}
One advantage of using C++ and its standard libraries over C and its standard libraries is precisely this: you almost never need to use pointers.
But, taking your program for what it is worth, there are sevearal problems. First, in C++, if you want to access the C header files, you should include them with their C++ names:
#include <cstdio>
#include <cstdlib>
Next, main requires a proper signature:
int main(int, char**) {
Most crucially, you are not allocating enough space for your user's name:
name = (char *)malloc(A_BIG_ENOUGH_NUMBER);
Here, you must allocate enough space that scanf() will not write beyond the end of your buffer. But, you can't possibly know how big that is until afte scanf runs. This catch-22 is the source of "buffer-overflow" bugs. For your test program, since you control the input, it is probably OK to just pick a number bigger than any name you'll ever type. In production code, you must NEVER, EVER, used scanf in this way.
name = (char *)mallocc(40);
By the way, if you are compiling this as C code, you should never cast the return from malloc. If you are compiling this as C++ code, you must always cast the return from malloc.
printf("%c", *name); name++
This line is missing a semicolon. Did you compile this program? In future, please only post code that you have compiled. Please use your computer's cut-and-paste features to post your code, never retype the code by hand.
This line has two other problems. First, you must derefence the name pointer to access the data to which it points. (So, *name instead of name.) Second, you need not dereference name in the second statement on this line, since you do nothing with the resulting pointed-to data. (So, name++ instead of *name++.)
Finally, and most importantly, buy, read, and learn from a good book.
Your program is likely printing junk because you only allocate one byte to your string buffer. When the user enters a string, you will have undefined behavior because the scanf will write past the end of name.
You need to alloc name like this:
char *name = (char *)malloc(MAX_STRING_SIZE, sizeof(char));
Even better to use calloc instead of malloc. Define MAX_STRING_SIZE however you like. A reasonable size depends on the application. In your case, if the users will be entering short strings, then perhaps a reasonable buffer size is 64 bytes, or perhaps 80 or 100.
Also, in your while loop, you can increment and dereference your pointer in one step, like this:
printf("%c", *name++);
If you don't like to be that terse, then you can break them apart, but you don't need to dereference the pointer to increment it.
printf("%c", *name); name++;
That's not C++, it's C.
malloc(sizeof(char)) will allocate storage of one char, I expect you wanted more than that.
Also there is no need to allocate dynamically here. Try:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
char name[256];
char *p = name;
printf("Enter string: ");
scanf("%s", name);
while (*p != '\0') {
printf("%c", *p);
p++;
}
return 0;
}