I have to make a pyramid only using C, no C++. what I have to do is this,
I have a string "this is a string " (yes the space is suppose to be there), and I have to "remove" one letter from both sides, and print that. like this
"this is a string "
"his is a string"
"is a strin"
"s a stri"
" a str"
This is repeated until there are no more characters. My teacher says to use substrings, is there any thing in C that says
print from location (index 0 to index x)
print from location (index 1 to index x-1)
I know I have to use a for loop.
This is homework, so I'll just get you started.
#include <stdio.h>
#include <string.h>
int main(void) {
char src[] = "this is a test string";
char dest[5] = {0}; // 4 chars + terminator
for (int i = 0; i * 4 < strlen(src); i++) {
strncpy(dest, src+(i*4), 4);
puts(dest);
}
}
Output:
this
is
a te
st s
trin
g
So for your pyramid problem, you will want to take the substring of the your original string. Set the beginning of your substring one character ahead of your original string, and strlen(original) - 1 for the end character. Then loop that process.
Yes, there is a printing facility enabling you to print substrings. Read the spec for printf.
There is a way to give it a parameter (int) which limits how many characters from another parameter (char*) it prints.
To chop off the first character of a string, simply treat the next character as the start of the string. So, instead of puts(str), call puts(str + 1).
To chop off the last character of a string, overwrite the last character with a \0 character. Since this is a destructive operation, it is probably a good idea to operate a copy of the original string.
To solve this problem, then, make a copy of the string. Keep two pointers: one at the front of the copied string walking towards the end, and one at the end walking towards the front.
Related
To solve a question, I am looking for a way to stop a loop after it has reached the beginning of the string, assuming the loop starts from the end and decrements, is there an alternative way to do this without finding the length of the string first and decrementing till the number is zero?
Please keep in mind the only functions I can use are malloc, free and write.
This is not possible, because there is nothing special about a string's contents at the beginning. C strings have a "sentinel value" at their end - '\0' - but the first character, and the byte in memory before the first character, can have any value.
is there an alternative way to do this without finding the length of the string first and decrementing till the number is zero?
Apparently you already know where the end of the string is. I suppose you must have a pointer to the terminator character, since you think you do not know the string length.
If finding the length of the string is a viable option at all, however, then you must already know where the beginning is, too. And if you know where the beginning is and you know where the end is, then you already know the length: it is end - beginning. But you do not need to keep a separate counter to iterate backward from the end of a string to the beginning, supposing that you do know where both the end and the beginning are. You can simply use pointer comparisons instead. For example:
int count_a_backwards(const char *beginning, const char *end) {
int count = 0;
for (const char *c = end; c > beginning; ) {
if (*--c == 'a') count += 1;
}
return count;
}
If in fact you do not know where the beginning of the string is, however, then you cannot identify it at all, at least not in the general case. Perhaps you can recognize the beginning if you have some kind of prior knowledge about the string's contents, or about its alignment, or some such, but in general, the beginning of a string cannot be recognized.
Please keep in mind the only functions I can use are malloc, free and
write.
If you are using the function malloc then the function returns pointer to the first byte of the allocated memory. So if the allocated array will contain a string then its beginning will be known.
The task is to find the end of the string.
You can use either the standard C function strlen or write your own loop that will find the end of the stored string.
So if you have two pointers, one that points to the beginning of a string and the second that points to the end of the same string then to traverse the string in the reverse order is not a hard work.
Pay attention to that if you have a character array that contains a string like this
char s[] = "Hello";
then the expressions s, s + 1, s + 2 and so on all points to a string correspondingly "Hello", "ello", "llo" and so on.
You could find the beginning of a string having a pointer to its end provided that the first element of the array contains a unique symbol that is a sentinel value. However in general this is a very rare case.
Here is a demonstrative program that shows how you can traverse a string in the reverse order without using standard C string functions except a function that places a string in a dynamically allocated array.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
enum { N = 12 };
char *s = malloc( N );
strcpy( s, "Hello World" );
puts( s );
char *p = s;
while ( *p ) ++p;
while ( p != s ) putchar( *--p );
putchar( '\n');
free( s );
return 0;
}
The program output is
Hello World
dlroW olleH
I'm trying to tokenize a phone number and split it into two arrays. It starts out in a string in the form of "(515) 555-5555". I'm looking to tokenize the area code, the first 3 digits, and the last 4 digits. The area code I would store in one array, and the other 7 digits in another one. Both arrays are to hold just the numbers themselves.
My code seems to work... sort of. The issue is when I print the two storage arrays, I find some quirks;
My array aCode; it stores the first 3 digits as I ask it to, but then it also prints some garbage values notched at the end. I walked through it in the debugger, and the array only stores what I'm asking it to store- the 515. So how come it's printing those garbage values? What gives?
My array aNum; I can append the tokens I need to the end of it, the only problem is I end up with an extra space at the front (which makes sense; I'm adding on to an empty array, ie adding on to empty space). I modify the code to only hold 7 variables just to mess around, I step into the debugger, and it tells me that the array holds and empty space and 6 of the digits I need- there's no room for the last one. Yet when I print it, the space AND all 7 digits are printed. How does that happen?
And how could I set up my strtok function so that it first copies the 3 digits before the "-", then appends to that the last 4 I need? All examples of tokenization I've seen utilize a while loop, which would mean I'd have to choose either strcat or strcpy to complete my task. I can set up an "if" statement to check for the size of the current token each time, but that seems too crude to me and I feel like there's a simpler method to this. Thanks all!
int main() {
char phoneNum[]= "(515) 555-5555";
char aCode[3];
char aNum[7];
char *numPtr;
numPtr = strtok(phoneNum, " ");
strncpy(aCode, &numPtr[1], 3);
printf("%s\n", aCode);
numPtr = strtok(&phoneNum[6], "-");
while (numPtr != NULL) {
strcat(aNum, numPtr);
numPtr = strtok(NULL, "-");
}
printf("%s", aNum);
}
I can primarily see two errors,
Being an array of 3 chars, aCode is not null-terminated here. Using it as an argument to %s format specifier in printf() invokes undefined behaviour. Same thing in a differrent way for aNum, too.
strcat() expects a null-terminated array for both the arguments. aNum is not null-terminated, when used for the first time, will result in UB, too. Always initialize your local variables.
Also, see other answers for a complete bug-free code.
The biggest problem in your code is undefined behavior: since you are reading a three-character constant into a three-character array, you have left no space for null terminator.
Since you are tokenizing a value in a very specific format of fixed length, you could get away with a very concise implementation that employs sscanf:
char *phoneNum = "(515) 555-5555";
char aCode[3+1];
char aNum[7+1];
sscanf(phoneNum, "(%3[0-9]) %3[0-9]-%4[0-9]", aCode, aNum, &aNum[3]);
printf("%s %s", aCode, aNum);
This solution passes the format (###) ###-#### directly to sscanf, and tells the function where each value needs to be placed. The only "trick" used above is passing &aNum[3] for the last argument, instructing sscanf to place data for the third segment into the same storage as the second segment, but starting at position 3.
Demo.
Your code has multiple issues
You allocate the wrong size for aCode, you should add 1 for the nul terminator byte and initialize the whole array to '\0' to ensure end of lines.
char aCode[4] = {'\0'};
You don't check if strtok() returns NULL.
numPtr = strtok(phoneNum, " ");
strncpy(aCode, &numPtr[1], 3);
Point 1, applies to aNum in strcat(aNum, numPtr) which will also fail because aNum is not yet initialized at the first call.
Subsequent calls to strtok() must have NULL as the first parameter, hence
numPtr = strtok(&phoneNum[6], "-");
is wrong, it should be
numPtr = strtok(NULL, "-");
Other answers have already mentioned the major issue, which is insufficient space in aCode and aNum for the terminating NUL character. The sscanf answer is also the cleanest for solving the problem, but given the restriction of using strtok, here's one possible solution to consider:
char phone_number[]= "(515) 555-1234";
char area[3+1] = "";
char digits[7+1] = "";
const char *separators = " (-)";
char *p = strtok(phone_number, separators);
if (p) {
int len = 0;
(void) snprintf(area, sizeof(area), "%s", p);
while (len < sizeof(digits) && (p = strtok(NULL, separators))) {
len += snprintf(digits + len, sizeof(digits) - len, "%s", p);
}
}
(void) printf("(%s) %s\n", area, digits);
I have an array of charracters where I put in information using a gets().
char inname[30];
gets(inname);
How can I add another character to this array without knowing the length of the string in c? (the part that are actual letters and not like empty memmory spaces of romething)
note: my buffer is long enough for what I want to ask the user (a filename, Probebly not many people have names longer that 29 characters)
Note that gets is prone to buffer overflow and should be avoided.
Reading a line of input:
char inname[30];
sscanf("%.*s", sizeof(inname), inname);
int len = strlen(inname);
// Remove trailing newline
if (len > 0 && inname[len-1] == '\n') {
len--;
inname[len] = '\0'
}
Appending to the string:
char *string_to_append = ".";
if (len + strlen(string_to_append) + 1) <= sizeof(inname)) {
// There is enough room to append the string
strcat(inname, string_to_append);
}
Optional way to append a single character to the string:
if (len < sizeof(inname) - 2) {
// There is room to add another character
inname[len++] = '.'; // Add a '.' character to the string.
inname[len] = '\0'; // Don't forget to nul-terminate
}
As you have asked in comment, to determine the string length you can directly use
strlen(inname);
OR
you can loop through string in a for loop until \0 is found.
Now after getting the length of prvious string you can append new string as
strcat(&inname[prevLength],"NEW STRING");
EDIT:
To find the Null Char you can write a for loop like this
for(int i =0;inname[i] != 0;i++)
{
//do nothing
}
Now you can use i direcly to copy any character at the end of string like:
inname[i] = Youe Char;
After this increment i and again copy Null char to(0) it.
P.S.
Any String in C end with a Null character termination. ASCII null char '\0' is equivalent to 0 in decimal.
You know that the final character of a C string is '\0', e.g. the array:
char foo[10]={"Hello"};
is equivalent to this array:
['H'] ['e'] ['l'] ['l'] ['0'] ['\0']
Thus you can iterate on the array until you find the '\0' character, and then you can substitute it with the character you want.
Alternatively you can use the function strcat of string.h library
Short answer is you can't.
In c you must know the length of the string to append char's to it, in other languages the same applies but it happens magically, and without a doubt, internally the same must be done.
c strings are defined as sequences of bytes terminated by a special byte, the nul character which has ascii code 0 and is represented by the character '\0' in c.
You must find this value to append characters before it, and then move it after the appended character, to illustrate this suppose you have
char hello[10] = "Hello";
then you want to append a '!' after the 'o' so you can just do this
size_t length;
length = strlen(hello);
/* move the '\0' one position after it's current position */
hello[length + 1] = hello[length];
hello[length] = '!';
now the string is "Hello!".
Of course, you should take car of hello being large enough to hold one extra character, that is also not automatic in c, which is one of the things I love about working with it because it gives you maximum flexibility.
You can of course use some available functions to achieve this without worrying about moving the '\0' for example, with
strcat(hello, "!");
you will achieve the same.
Both strlen() and strcat() are defined in string.h header.
Just double checking because I keep mixing up C and C++ or C# but say that I have a string that I was parsing using strcspn(). It returns the length of the string up until the first delimiter it finds. Using strncpy (is that C++ only or was that available in C also?) I copy the first part of the string somewhere else and have a variable store my position. Let's say strcspn returned 10 (so the delimiter is the 10th character)
Now, my code does some other stuff and eventually I want to keep traversing the string. Do I have to copy the second half of the string and then call strncspn() from the beginning. Can I just make a pointer and point it at the 11th character of my string and pass that to strncspn() (I guess something like char* pos = str[11])? Something else simpler I'm just missing?
You can get a pointer to a location in the middle of the string and you don't need to copy the second half of the string to do it.
char * offset = str + 10;
and
char * offset = &str[10];
mean the same thing and both do what you want.
You mean str[9] for the 10th char, or str[10] for the 11th, but yes you can do that.
Just be careful that you are not accessing beyond the length of the string and beyond the size of memory allocated.
It sounds like you are performing tokenization, I would suggest that you can directly use strtok instead, it would be cleaner, and it already handles both of what you want to do (strcspn+strncpy and continue parsing after the delimiter).
you can call strcspn again with (str + 11) as first argument. But make sure that length of str is greater than 11.
n = strcspn(str, pattern);
while ((n+1) < strlen(str))
{
n2 = strcspn((str+n), pattern);
n += n2;
}
Note : using char *pos = str[11] is wrong. You should use like char *pos = str + 11;
I'm really surprised I can't figure out a way to do this effectively. I've tried strstr, a combination of things with sscanf, and nothing seems to work the way I would expect it to based on my experience in other languages.
I have a char of "ABCDEFG HIJ K BEGINTheMiddleEND LMNO PQRS". I do not know where "BEGINTheMiddleEND" is in the string, and I would like to end with a char that equals "TheMiddle" by finding the occurrences of "BEGIN" and "END" and grabbing what is in between.
What is the most efficient way to accomplish this (find and sub-string)?
Thanks!
-- EDIT BASED ON ANSWERS --
I have tried this:
char *searchString = "ABCDEFG HIJ K BEGINTheMiddleEND LMNO PQRS"
char *t1, *t2;
t1 = strstr(searchString, "BEGIN");
t2 = strstr(t1, "END");
But something must be wrong from a pointer standpoint as it doesn't work for me. Strstr only takes two arguments, so I'm not sure what you mean by starting at the previous pointer. I'm also not sure how to then use those pointers to substring it, as they are not integer values like strpos returns, but character pointers.
Thanks again.
-- EDIT WITH FINAL CODE --
For anyone else who hits this, the final, working code:
char *searchString = "ABCDEFG HIJ K BEGINTheMiddleEND LMNO PQRS"
char *b = strstr(searchString , "BEGIN");
char *e = strstr(b, "END");
int offset = e - b;
b[offset] = 0;
Where "b" is now equal to "BEGINTheMiddle". (which as it turns out is what I needed in this case).
Thanks again everyone.
You need to realize what a string is. A 0 delimited sequence of chars.
strstr does what it says: it finds the beginning of the given substring.
So calling strstr with the needle "BEGIN" takes you to the position of this substring. The pointer pointing to "BEGIN", advanced by 5 characters is pointing to "TheMiddle" onward to the next 0 char. By searching for "END" you can find the end pointer, and then you need to copy the substring into a new string array (or cut it, by replacing the "E" with a 0; or implement your own string functions that do not use 0 terminated strings, so they can arbitrarily overlap).
That is probably the step that you are still missing: actually copy the string. E.g. using
t3 = strndup(t1, t2 - t1);
Take the string ABCDEF0, where 0 is an actual 0 character. A pointer to the beginning points to the full string, a pointer pointing to the E points to "EF" only. If you want to get a string "AB", you need to either copy that to "AB0", or replace C by 0.
strstr does not do the copying for you. It just finds the position. If you want an index, you can do int offset = newPosition - oldPosition;, but if you need to continue searching, it's easier to work with the newPosition pointer.
All this is less intuitive than e.g. String operations in Java. Except for truncating strings, it actually is more efficient as far as I know, and if you realize the 0-terminated memory layout, it makes a lot of sense. It's only when you think of strings as arrays that it may seem odd to have a pointer somewhere in the middle, and continue using it like a regular array. That makes "sub = string + offset" the C way of writing "sub = string.substring(offset)".
use strstr() twice, but the sencond time start from the position returned by the first call to strstr() + strlen(BEGIN).
This will be efficient because the first pointer returned from strstr() is going to be the beginning of BEGIN, therefore you won't be looking through the whole string again but start at the BEGIN-ing and look for the END from there; which means that at the most you run through the whole string once.
I hope this will help
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int strpos(char *haystack, char *needle, int offset);
int main()
{
char *p = "Hello there all y'al, hope that you are all well";
int pos = strpos(p, "all", 0);
printf("First all at : %d\n", pos);
pos = strpos(p, "all", 10);
printf("Second all at : %d\n", pos);
}
int strpos(char *hay, char *needle, int offset)
{
char haystack[strlen(hay)];
strncpy(haystack, hay+offset, strlen(hay)-offset);
char *p = strstr(haystack, needle);
if (p)
return p - haystack+offset;
return -1;
}