What is strncpy

In this code the function strncpy accepts 4 arguments but in the reference here at cplusplus.com it only accepts 3?

Reference: http://www.cplusplus.com/reference/cstring/strncpy/

The function is on line 182

Can anyone explain please?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
// Ex6_10Extended.cpp
// A program to implement a calculator accepting parentheses

#include <iostream>                   // For stream input/output
#include <cstdlib>                    // For the exit() function
#include <cctype>                     // For the isdigit() function
#include <cstring>                    // For the strcpy() function
using std::cin;
using std::cout;
using std::cerr;
using std::endl;

void eatspaces(char* str);            // Function to eliminate blanks
double expr(char* str);               // Function evaluating an expression
double term(char* str, int& index);   // Function analyzing a term
double number(char* str, int& index); // Function to recognize a number
char* extract(char* str, int& index); // Function to extract a substring
const int MAX(80);                    // Maximum expression length, 
                                      // including '\0'
int main()
{
   char buffer[MAX] = {0};    // Input area for expression to be evaluated

   cout << endl
        << "Welcome to your friendly calculator."
        << endl
        << "Enter an expression, or an empty line to quit."
        << endl;

   for(;;)
   {
      cin.getline(buffer, sizeof buffer);   // Read an input line
      eatspaces(buffer);                    // Remove blanks from input

      if(!buffer[0])                        // Empty line ends calculator
         return 0;

      try
      {
        cout << "\t= " << expr(buffer)      // Output value of expression
             << endl << endl;
      }
      catch( const char* pEx)
      {
        cerr << pEx << endl;
        cerr << "Ending program." << endl;
        return 1;
      }
   }
}


// Function to eliminate spaces from a string
void eatspaces(char* str)
{
   int i(0);                              // 'Copy to' index to string
   int j(0);                              // 'Copy from' index to string

   while((*(str + i) = *(str + j++)) != '\0')  // Loop while character
                                               // copied is not \0
      if(*(str + i) != ' ')                    // Increment i as long as
         i++;                                  // character is not a space
   return;
}

// Function to evaluate an arithmetic expression
double expr(char* str)
{
  double value(0.0);                   // Store result here
  int index(0);                        // Keeps track of current character position

  value = term(str, index);            // Get first term

  for(;;)                              // Indefinite loop, all exits inside
  {
    switch(*(str + index++))           // Choose action based on current character
    {
      case '\0':                       // We're at the end of the string
         return value;                 // so return what we have got

      case '+':                        // + found so add in the
         value += term(str, index);    // next term
         break;

      case '-':                        // - found so subtract
         value -= term(str, index);    // the next term
         break;

      default:                         // If we reach here the string
         char message[38] = "Expression evaluation error. Found: ";
         strncat_s(message, str + index - 1, 1);  // Append the character
         throw message;
         break;
    }
  }
}

// Function to get the value of a term
double term(char* str, int& index)
{
  double value(0.0);                   // Somewhere to accumulate 
                                       // the result

  value = number(str, index);          // Get the first number in the term

  // Loop as long as we have a good operator
  while(true)
  {

    if(*(str + index) == '*')          // If it's multiply,
      value *= number(str, ++index);   // multiply by next number

    else if(*(str + index) == '/')     // If it's divide,
      value /= number(str, ++index);   // divide by next number
    else
      break;
  }
  return value;                        // We've finished, so return what 
                                       // we've got
}

// Function to recognize a number in a string
double number(char* str, int& index)
{
  double value(0.0);                   // Store the resulting value

  if(*(str + index) == '(')            // Start of parentheses
  {
    char* psubstr(nullptr);            // Pointer for substring
    psubstr = extract(str, ++index);   // Extract substring in brackets
    value = expr(psubstr);             // Get the value of the substring
    delete[]psubstr;                   // Clean up the free store
    return value;                      // Return substring value
  }

  // There must be at least one digit...
  if(!isdigit(*(str + index)))
  { // There's no digits so input is junk...
    char message[31] = "Invalid character in number: ";
    strncat_s(message, str+index, 1);  // Append the character
    throw message;
  }

  while(isdigit(*(str + index)))       // Loop accumulating leading digits
    value = 10*value + (*(str + index++) - '0');

                                       // Not a digit when we get to here
  if(*(str + index) != '.')            // so check for decimal point
    return value;                      // and if not, return value

  double factor(1.0);                  // Factor for decimal places
  while(isdigit(*(str + (++index))))   // Loop as long as we have digits
  {
    factor *= 0.1;                     // Decrease factor by factor of 10
    value = value + (*(str + index) - '0')*factor;   // Add decimal place
  }

  return value;                        // On loop exit we are done
}

// Function to extract a substring between parentheses 
// (requires cstring)
char* extract(char* str, int& index)
{
  char* pstr(nullptr);                // Pointer to new string for return
  int numL(0);                        // Count of left parentheses found
  int bufindex(index);                // Save starting value for index

  do
  {
    switch(*(str + index))
    {
      case ')':
        if(0 == numL)
        {
          ++index;
          pstr = new char[index - bufindex];
          if(!pstr)
          {
            throw "Memory allocation failed.";
          }
          strncpy_s(pstr, index-bufindex, str+bufindex, index-bufindex-1); // Copy substring to new memory
          return pstr;                                                     // Return substring in new memory
        }
        else
          numL--;                                                          // Reduce count of '(' to be matched
          break;

      case '(':
        numL++;                                                            // Increase count of '(' to be 
                                                                           // matched
        break;
      }
  } while(*(str + index++) != '\0');                                       // Loop - don't overrun end of string

  throw "Ran off the end of the expression, must be bad input.";
}
Last edited on
Since when is strncpy_s() the same as strncpy()?
http://msdn.microsoft.com/en-us/library/5dae5d43%28v=vs.80%29.aspx

And seriously, if you're already using C++, you should favor std::string and the STL algorithms.
I am just doing this cause my book starts off with c style strings and moves on to std::string later.
You have a bad book. A very large majority of modern C++ programmers believe that std::string should be taught before c-style strings.
Can you recommend any books please LB?
I can't, but the combined effort of the internet and everyone in it can:
http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list
But I am still interesting in this. Why does strncat_s accept 3 arguments.

Is it because of function overloading maybe. One has different parameters then the other because here it takes 3 arguments and it is strncat_s but on msdn it says it takes 4?

Do you know where I can find the cstring library?
Last edited on
@Anmol444
They are two different functions. The c standard function is strncat(), the windows only safe string function is strncat_s(), it takes 4 arguments because you pass it the size of the source and destination, and the number of chars in source to append. If you want portability stick to the standard function.
Last edited on
No but my question is that strncat_s accepts 3 arguments here but on the msdn site it says it accepts 4 arguments. Sorry made a typo on my last post. xD
Anmol444 wrote:
No but my question is that strncat_s accepts 3 arguments here but on the msdn site it says it accepts 4 arguments. Sorry made a typo on my last post. xD


Looks like there is a template function I didn't notice before.
1
2
3
4
5
6
template <size_t size>
errno_t strncat_s(
   char (&strDest)[size],
   const char *strSource,
   size_t count
); // C++ only 
Where is that? Is it in cstring? If so where is cstring located so I can investigate?
Stop here. This is only for one operating system, it is non standard and subject to change, and you shouldn't use it, let alone investigate it.
Ok I wont. Cstring is nonstandard? So std::string is the standard right?
UNIX/Linux Programming
Programming C++ for UNIX and Linux

strncat_s
Compatibility
Windows 95, Windows 98, Windows 98 Second Edition, Windows Millennium Edition, Windows NT 4.0, Windows 2000, Windows XP Home Edition, Windows XP Professional, Windows Server 2003


¿?
Ok I wont. Cstring is nonstandard? So std::string is the standard right?


Remember how you couldn't find strncpy_s() and strncat_s() in this site's Reference? But you could find strncpy() and strncat()?

Hint: if it's in on of these two references below, then it's standard, 99.9% of the time.
http://cplusplus.com/reference/
http://en.cppreference.com/w/

Also *blah blah* backwards compatibility *blah blah* duplicate features *blah* newer, better *blah blah* horrible language.
Ok
Topic archived. No new replies allowed.