"strncpy_s" Not Working - c++

I'm trying to use strncpy_s to characters from one word to an array (I cannot use strncpy in Visual Studio 2013 and I'm totally new to strncpy_s). I keep getting these errors whatever I do:
Error 1 error C2660: 'strncpy_s' : function does not take 3 arguments
Error 2 IntelliSense: no instance of overloaded function "strncpy_s"
matches the argument list argument types are: (char *, char, int)
The purpose of my code is:
If user inputs, for example, "HELLO" (that is, text = HELLO)
Then ->
Copy HELLO to first_array [0]
Copy ELLO to first_array [1]
Copy LLO to first_array [2]
Copy LO to first_array [3]
Copy O to first_array [4]
And here's my code:
int _tmain(int argc, _TCHAR* argv[])
{
char text[32];
cin >> text;
char* first_array[] = {""};
int n = strlen(text);
for (int i = 0; i < n; i++)
{
strncpy_s(first_array[i], text[i], n-i);
}
}
EDIT 1. Modified the code a bit more, now the program runs, but after inputing a text, it suddenly gives me the "example.exe stopped working" error.
int _tmain(int argc, _TCHAR* argv[])
{
char* text[32];
cin >> *text;
char* first_array[] = {""};
//int n = strlen(text);
int n = sizeof(text);
for (int i = 0; i < n; i++)
{
strncpy_s(first_array[i], n - i, text[i], 32);
}

Your code has several issues.
First of all, your call to strncpy_s does not follow the declaration of strncpy_s, which lists four parameters (if the first parameter is a char * as in your case):
errno_t strncpy_s(
char *strDest,
size_t numberOfElements,
const char *strSource,
size_t count
);
But much more importantly, you state that you would like to end up with multiple strings in an array first_array[], each holding a shorter version of the input string than the last. But the first_array[] you declared only holds one char * string, the one you initialized first_array[0] to, which is exactly one character long (the terminating null byte):
char* first_array[] = {""};
Even if you declared it to hold five char * (the initialization is not necessary as you copy the contents over anyway)...
char * first_array[5];
...you still haven't allocated memory space for each of the five char * strings. You just have five pointers pointing nowhere, and would have to allocate memory dynamically, depending on user input.
Because I haven't even talked about what happens if the user enters more than five characters, let alone 32...
At this point, even if I would post "working" code, it would teach you little. You are apparently following some kind of tutorial, or actually attempting to learn by trial & error. I think the right answer here would be:
Get a different tutorial. Even better, get a good book on C or a good book on C++ as online tutorials are notoriously lacking.

Related

Is it valid to append a string to a character array like char p [] = "TEST" using strcat

#include<iostream>
#include<string.h>
using namespace std;
int main()
{
char p [] = "TEST";
strcat (p, "VAL");
cout << p;
return 0;
}
If what I understand is correct, a statement like char p [] = "TEST"; will allocate space from stack. When I call strcat() for such a string how the storage for p[] is adjusted to accommodate extra characters?
Last cout prints "TESTVAL". Is it valid to call strcat like this? If yes, how this works? I might be having problem with my understanding, but feeling like I lost touch. So this could easily be a dumb question. Please shed some light.
The storage is not adjusted, the call is not valid, and the behaviour of the code is undefined.
when you write
char buffer[] = "some literal";
it is expanded to
char buffer[sizeof("some literal")] = "some literal";
which has exact size to store "some literal" and nothing more.
when you concate another string in the end of the current buffer- you write beyond the boundries of the array - having undefined behavior.
another issue that in C++, we usually use std::string to handle strings, which does all the memory adjustment for us automatically.
p reserves space for 5 characters (4 + 1 for the null terminator). You are then appending 3 more characters which needs room for 8 (7 + 1 for the null). You don't have enough room for that and will be overwriting the stack. Depending on your compiler and build settings, you may not see any difference as potentially, the compiler leaves spaces between stack variables. On an optimised release build, you will probably get a crash.
If you change your code to look like this, you should see that sentinel1 & 2 are no longer 0 (it depends on the compiler which one will get trashed).
#include<iostream>
#include<string.h>
using namespace std;
int main()
{
int sentinel1 = 0;
char p [] = "TEST";
int sentinel2 = 0;
strcat (p, "VAL");
cout << p << sentinel1 << sentinel2;
return 0;
}

Reverse a string with pointers [duplicate]

This question already has answers here:
C++ Reverse Array
(5 answers)
Closed 7 years ago.
This is an amateur question. I searched for other posts about this topic, found lots of results, but am yet to understand the concepts behind the solution.
This is a practice problem in my C++ book. It is not assigned homework. [Instructions here][1] .
WHAT I WOULD LIKE TO DO:
string input;
getline(cin, input); //Get the user's input.
int front = 0;
int rear;
rear = input.size();
WHAT THE PROBLEM WANTS ME TO DO
string input;
getline(cin, input); //Get the user's input.
int* front = 0;
int* rear;
rear = input.size();
Error: a value of type "size_t" cannot be assigned to an entity of type int*
This makes sense to me, as you cannot assign an 'address' of an int to the value of an int.
So my questions are:
What is the correct way to go about this? Should I just forget about initializing front* or rear* to ints? Just avoid that all together? If so, what would be the syntax of that solution?
Why would this problem want me to use pointers like this? It's clear this is a horrible usage of pointers. Without pointers I could complete this problem in like 30 seconds. It's just really frustrating.
I don't really see an advantage to EVER using pointers aside from doing something like returning an array by using pointers.
Thanks guys. I know you like to help users that help themselves so I did some research about this first. I'm just really irritated with the concept of pointers right now vs. just using the actual variable itself.
Posts about this topic that I've previously read:
[Example 1][2]
[Example 2][3]
[Example 3][4]
[1]: http://i.imgur.com/wlufckg.png "Instructions"
[2]: How does reversing a string with pointers works "Post 1"
[3]: Reverse string with pointers? "Post 2"
[4]: Reverse char string with pointers "Post 3"
string.size() does not return a pointer - it returns size_t.
To revert a string try this instead:
string original = "someText"; // The original string
string reversed = original; // This to make sure that the reversed string has same size as the original string
size_t x = original.size(); // Get the size of the original string
for (size_t i = 0; i < x; i++) // Loop to copy from end of original to start of reversed
{
reversed[i]=original[x-1-i];
}
If you really (for some strange reason) needs pointers try this:
string input;
getline(cin, input); //Get the user's input.
char* front = &input[0];
char* rear = &input[input.size()-1];
but I would not use pointers into a string. No need for it.
I guest you may not quite understand the problem here. This problem want you to COPY a C string then REVERSE it by pointer operation. There is no classes in standard C. So, the C string is quite different from string class in C++. It is actually an array of char-type elements ended with character '\0'.
After understand this, you may start to understand the problem here. If you want to copy a C string, you can not just use str_a = str_b. You need constructor here. However, in pure C style, you should REQUIRE memory space for the string at first (you can use malloc here), then copy each element. For example, you want to create a function to make a copy of input string,
#include <string.h>
char *strcopy(char* str_in) {
int len = strlen(str_in);
char *str_out = (char*)malloc(len+1);
char *in = str_in;
char *out = str_out;
while(*in != '\0') { *out++ = *in++; }
return str_out;
}
As you see, we actually use char* not int* here to operate string element. You should distinguish the pointer (such as in) and the element pointed by the pointer (such as *in) at first.
I'll show you a solution in pure C style for your problem, I hope this would help you to understand it. (You should be able to compile it without modification)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* strreverse(char* in){
// length of input string
int len = strlen(in);
// allocate memory for string operation
char *out = (char*)malloc(len+1);
// initialize <front> and <end>
char *front = out, *end = out + len - 1;
char buffer;
// copy input string
for(int i = 0; i <= len; i++){ out[i] = in[i]; }
// reverse string
for(; front < end; front++, end--) {
buffer = *front;
*front = *end;
*end = buffer;
}
return out;
}
int main() {
printf("REVERSE >> %s\n", strreverse("Hello, World!"));
return 0;
}
This is not you would do by C++ in actual programming, however, I guess the problem here is trying to let you understand mechanism of pointers. In this aspect, original C style would help a lot.

About pointers and arrays [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
#include<stdio.h>
#include<stdlib.h>
char *syllable[26] = {"a","bub","cash","dud","e","fud","gug","hash","i","jay",
"kuck","lul","mum","nun","o","pub","quack","rug","sus",
"tut","u","vuv","wack","xux","yuck","zug"};
void Tutnese(char *word, char *newword);
char *letter;
void Tutnese(char *word, char *newword)
{
//clrscr();
for(*letter = 'A'; *letter <= 'Z'; *letter++)
{
letter=syllable;
printf("%c\n",&letter);
}
}
Tutnese is an English language game primarily used by children who use it to converse in
(perceived) privacy from adults (or vice versa)
I am trying to let A="A" B="bub" c="cash" and so on.
I am expecting a result like this.
“computer.” becomes “cashomumpubututerug.”
- “Stony” become “Sustutonunyuck”
but i just start learning c, and i have no idea how to use pointer. I've been keep getting error like assignment makes integer from pointer without a cast
char *letter;
This statement declares a variable named letter, same way as any other statement like char ch; will do.
Now, what's the difference then!!
Well the difference (and similarity) is:
char ch; declares a char variable, i.e. a memory block of size 1 byte is allocated (statically), which you can refer to using ch.
char *letter; on the other hand declares a char pointer i.e. a memory size of 2 or 4 or 8 bytes (depending on compiler) will be allocated (again statically) to store address of a char variable.
Now when you use *letter as lvalue (on Left Hand Side) as you do in for loop, this means you are trying to write to the memory address stored in letter. In your case you never stored any address in letter, to do so you can use letter = &ch; where ch is some char variable.
That was all the lecture!!
Now my suggestion for your program:
You don't need to use letter pointer for the loop, a simple char i variable will be fine.
To re-form the string as you plan to, you can simply use the characters of the original string as indices to form new string. Declare a empty string of some large length, then keep concatenating the syllable[orig_string[i] - 'A'], inside a for loop till the end of orig_string. Assumption is orig_string contains all uppercase alphabets
Finally, Correct your printf syntax.
Do read about pointers in C from a good source, as they will never leave you, and will give you all sorts of nightmare.
Code
#include <ctype.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *syllable[26] = {"a","bub","cash","dud","e","fud","gug","hash","i","jay",
"kuck","lul","mum","nun","o","pub","quack","rug","sus",
"tut","u","vuv","wack","xux","yuck","zug"};
void Tutnese(char *word, char *newword, size_t new_size);
void Tutnese(char *word, char *newword, size_t new_size)
{
char *end = newword + new_size;
char c;
while ((c = *word++) != '\0')
{
if (!isalpha(c))
*newword++ = c;
else
{
char *tut = syllable[tolower(c) - 'a'];
ptrdiff_t len = strlen(tut);
if (end - newword <= len)
break;
memcpy(newword, tut, len + 1);
newword += len;
}
}
*newword = '\0';
}
int main(void)
{
char i_data[1024];
char o_data[4096];
while (fgets(i_data, sizeof(i_data), stdin) != 0)
{
Tutnese(i_data, o_data, sizeof(o_data));
printf("I: %sO: %s", i_data, o_data);
}
return(0);
}
Output
I: computer
O: cashomumpubututerug
I: how do you tell mum that she cannot understand us?
O: hashowack dudo yuckou tutelullul mumumum tuthashatut sushashe cashanunnunotut ununduderugsustutanundud usus?
I: The quick brown fox jumped over the lazy dog.
O: tuthashe quackuicashkuck bubrugowacknun fudoxux jayumumpubedud ovuverug tuthashe lulazugyuck dudogug.
Lets forget about pointers and break down the problem.
You're given a word word and you want to create newword based on your mapping.
First, you need to figure out how big newword is.
To do that, iterate through the characters in word and add the string lengths of the mappings (call it N)
Once you've done that, you know you can allocate N+1 bytes (strings are null terminated in C) for newword (via malloc).
Then, you iterate through the characters again and just append to newword
Let me give you a few hints:
To iterate through a string (lets call it word), the C code would look like:
unsigned int wordlen = strlen(word);
for(unsigned int index = 0; index < wordlen; index++)
printf("Character at %u is %c", index, word[index]);
Your for loop is quite messed up. Do look up a few tutorials on pointers and string manipulation in C.

Segfaults on appending char* arrays

I'm making a lexical analyzer and this is a function out of the whole thing. This function takes as argument a char, c, and appends this char to the end of an already defined char* array (yytext). It then increments the length of the text (yylen).
I keep getting segfaults on the shown line when it enters this function. What am I doing wrong here? Thanks.
BTW: can't use the strncpy/strcat, etc. (although if you want you can show me that implementation too)
This is my code:
extern char *yytext;
extern int *yylen;
void consume(char c){
int s = *yylen + 1; //gets yylen (length of yytext) and adds 1
//now seg faults here
char* newArray = new char[s];
for (int i = 0;i < s - 1;i++){
newArray[i] = yytext[i]; //copy all chars from existing yytext into newArray
}
newArray[s-1] = c; //append c to the end of newArray
for (int i = 0;i < s;i++){ //copy all chars + c back to yytext
yytext[i] = newArray[i];
}
yylen++;
}
You have
extern int *yylen;
but try to use it like so:
int s = (int)yylen + 1;
If the variable is an int *, use it like an int * and dereference to get the int. If it is supposed to be an int, then declare it as such.
That can t work:
int s = (int)yylen + 1; //gets yylen (length of yytext) and adds 1
char newArray[s];
use malloc or a big enought buffer
char * newarray=(char*)(malloc(s));
Every C-style string should be null-terminated. From your description it seems you need to append the character at c. So, you need 2 extra locations ( one is for appending the character and other for null-terminator ).
Next, yylen is of type int *. You need to dereference it to get the length (assuming it is pointing to valid memory location ). So, try -
int s = *yylen + 2;
I don't see the need of temporary array but there might be a reason why you are doing it. Now,
yytext[i] = newArray[i]; //seg faults here
you have to check if yytext is pointing to a valid write memory location. If yes, then is it long enough to fill the appending character plus null terminator.
But I would recommend using std::string than working with character arrays. Using it would be a one liner to solve the problem.

Assigning chars to a char array with +=

Currently I'm writing a rather extensive homework assignment that - among other things - reads a file, builds a binary search tree and outputs it.
Somewhere inside all that I've written a recursive method to output the values of the binary search tree in order.
void output(node* n)
{
if(n->leftChild != NULL)
output(n->leftChild);
cout << n->keyAndValue << " || ";
outputString += n->keyAndValue << '|';
if(n->rightChild != NULL)
output(n->rightChild);
}
No problem with that, but you'll notice the line outputString += n->keyAndValue << '|';, because I also want to have all the values inside a char array (I am not allowed to use strings or other more current features of C++) that I can use later on in a different method (e.g. Main method).
The Char-Array is declared as follows:
char *outputString;
This being just one of the ways I've tried. I also tried using the const keyword and just regularly building an array char outputString[]. With the version I've shown you I encounter an error when - later on in the program in a different method - calling the following code:
cout << outputString;
I get the following error:
Unhandled exception at 0x008c2c2a in BST.exe: 0xC00000005: Access Violation reading location 0x5000000000.
Any clue as to how I'd be able to build a dynamic char array, assign values to it numerous times using += and outputting it without triggering an access violation? I am sorry for asking a rather basic question but I am entirely new to C++.
Thanks and Regards,
Dennis
I'm guessing that since you can't use std::string, you also can't use new[].
You can concatenate strings with a function like this:
char *concat(const char *s1, const char *s2)
{
size_t len = strlen(s1) + strlen(s2);
char *result = (char*)malloc(len+1);
strcpy(result, s1);
strcat(result, s2);
return result;
}
This can be done more efficiently, but that probably doesn't matter for homework. And you need to check for errors, etc. etc.
You also need to decide who is going to call free on s1 and s2.
For what it is worth, the efficient version looks like this:
char *concat(const char *s1, const char *s2)
{
size_t len1 = strlen(s1);
size_t len2 = strlen(s2);
char *result = (char*)malloc(len1+len2+1);
memcpy(result, s1, len1);
memcpy(result+len1, s2, len2);
result[len1+len2] = '\0';
return result;
}
It's more efficient because it only walks the input strings once.
+= on pointers does pointer arithmetic, not string concatenation. Eventually you get way beyond your array that outputString was pointing to, and trying to print it leads to a segfault.
Since you can't use std::string, you need to use strcat along with new[] and delete[] and make sure you allocated your original array with new[].