I'm trying to get characters from a String^ to put into a stack to use later, but when I check what actually gets put in it always has a number in front of it which messes up using it later (e.g. If I try to get a "-" character from within my string it shows as " 45 "-" ").
String^ input = "8-2";
char Temp = input[1];
The Temp variable will show as = 45 "-"
I'd like it to just save to the char as "-" only so I add it to a stack and call it later with Peek() but I can't figure out how.
45 is the ASCII code of the character -. It's showing you your data as both integer and character.
"char" (when using C++/CLI) is a C/C++ type (a one-byte representation of a 'character'). It's not a .NET type. Try Char (e.g. System::Char) instead and see if that works.
Related
I need to replace some %20 by spaces and got compile errors which i do not understand:
CString str = _T("foo%20bar");
str.Replace('%20',' '); // C4305 argument: truncation from 'int' to 'wchar_t'
str.Replace(_T('%20'),_T(' ')); // C4305 argument: truncation from 'int' to 'wchar_t'
str.Replace(_T("%20"),_T(" ")); // C2664 'int ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t>>>::Replace(const wchar_t *,const wchar_t *)': cannot convert argument 1 from 'const char [4]' to 'wchar_t'
What is wrong?
The CString::Replace() method takes null-terminated string pointers as input, not individual characters. Your string literals need to use " instead of ', eg:
CString str = _T("foo%20bar");
str.Replace(_T("%20"), _T(" "));
Note that matches your last example, which you say is also erroring. The only way that can fail with the error message you have shown is if you have a misconfiguration in your project, where UNICODE is defined 1 but _UNICODE is not defined 2.
1: as evident by CString being mapped to CStringT<wchar_t>.
2: as evident by the compiler saying _T("%20") is a const char[] rather than a const wchar_t[].
CString uses TCHAR from the Win32 API, not _TCHAR from the C runtime library. Usually they are interchangeable, but not so in your situation. So, you need to either fix your project's configuration so that _UNICODE is also defined, or else use the Win32 TEXT() macro to match CString's use of TCHAR:
CString str = TEXT("foo%20bar");
str.Replace(TEXT("%20"), TEXT(" "));
Or, simply stop using TCHAR-based APIs altogether (TCHAR dates back to the days of Win9x/ME when Microsoft was pushing everyone to start migrating their code to Unicode), and really should not be used in modern coding if you can avoid it. Just use wchar_t strings directly instead, eg:
CStringW str = L"foo%20bar";
str.Replace(L"%20", L" ");
The last one should have worked, except that you seem to have a wide CString in a project without the UNICODE and/or _UNICODE macro defined.
In this combination, the _T() macro isn't giving you a compatible string literal. But L"whatever" will.
str.Replace(L"%20", L" ");
Notice that this does what you asked, but is not adequate for URL unescaping. You should convert all %xx sequences.
%20 may be formatted string like %d. and Replace function return replaced String and str is not replaced.
try like: str = str.Replace(_T("%%20"), _T(" "));
or
try like: str = str.Replace(_T("%20"),_T(" "));
Extra Info
If you look at this Format specification syntax: printf and wprintf functions article you will see the following clarification:
A basic conversion specification contains only the percent sign and a type character. For example, %s specifies a string conversion. To print a percent-sign character, use %%. ...
In some programming languages, such as C for example, the end of string may be marked as a separate null terminator symbol.
How do I determine if the current symbol is the end of string?
Currently I use some string functions' calls, but I guess it may be performed easier.
*the string's end
IF ISBLANK(SUBSTR(str, pos, 1) == .T. AND CHR(32) != SUBSTR(str, pos, 1)
RETURN .T.
ENDIF
There's no need to worry about C-style string termination in VFP.
Assuming you don't care what the last character is then from your example:
return (pos = len(str))
If you want to ignore spaces:
return (pos = len(alltrim(str))
VFP strings are not ASCIIZ strings as in C. A VFP string can contain any ASCII character including character 0 - chr(0)- which is a string termination character in C style languages.
Normally the end of the string in VFP is the same as its length. But, although it is not clear from your question, sometimes you get a string from a C source (ie: a win32 call) where multiple string values are separated by chr(0) values. You can easily parse such a string into multiple string with a code like alines(). ie:
? ALines(laLines, "hello"+Chr(0)+"there",1+4,Chr(0)) && prints 2
display memory like laLines && shows two string values
Also you could use many string function like at(), occurs(), asc() ... to locate, count ... that character.
I'm having bad times trying to add a string inside of another string in a especific position. Every time I use this code, the rest of the string become blank.
double temperature = 22.1;
unsigned char pacote[16] = "#0123456789ABCDEF";
unsigned char temp_local[3];
dtostrf(temperatura, 3, 1, temp_local);
sprintf(pacote+3,"%s", temp_local);
or
sprintf(pacote+3,temp_local);
got the same printf:
#0122.1
istead of:
#0122.16789ABCDEF
Why is it erasing all the rest of the string and not just replace the next 4 positions after [3] and leaving the rest alone.
I'm using arduino but I think that's generic C question.
Thank you very much!!!
You should move the string data into the designated position (instead of copying the string, which includes a terminating '\0'):
memcpy(pacote+3, temp_local, strlen(temp_local));
if you are using C++ then use string::substr as in
new_string = old_string.substr(0,3) + "some text" + old_string.substr(3);
In pure C you first need to ensure that the destination has enough space. sprintf returns the number of characters written. Use this to ensure that destination has sufficient space. Then concatenate the two substrings with the new string as desired.
I am reading from a file in Fortran which has an undetermined number of floating point values on each line (for now, there are about 17 values on a line). I would like to read the 'n'th value on each line to a given floating point variable. How should i go about doing this?
In C the way I wrote it was to read the entire line onto the string and then do something like the following:
for(int il = 0; il < l; il++)
{
for(int im = -il; im <= il; im++)
pch = strtok(NULL, "\t ");
}
for(int im = -l; im <= m; im++)
pch = strtok(NULL, "\t ");
dval = atof(pch);
Here I am continually reading a value and throwing it away (thus shortening the string) until I am ready to accept the value I am trying to read.
Is there any way I can do this in Fortran? Is there a better way to do this in Fortran? The problem with my Fortran code seems to be that read(tline, '(f10.15)') tline1 does not shorten tline (tline is my string holding the entire line and tline1 what i am trying to parse it into), thus I cannot use the same method as I did in my C routine.
Any help?
The issue is that Fortran is a record-based I/O system while C is stream-based.
If you have access to a Fortran 2003 compliant compiler (modern versions of gfortran should work), you can use the stream ACCESS specifier to do what you want.
An example can be found here.
Of course, if you were really inclined, you could just use your C function directly from Fortran. Interfacing the two languages is generally simple, typically only requiring a wrapper with a lowercase name and an appended underscore (depending on compiler and platform of course). Passing arrays or strings back and forth is not so trivial typically; but for this example that wouldn't be needed.
Once the data is in a character array, you can read it into another variable as you are doing with the ADVANCE=no signature, ie.
do i = 1, numberIWant
read(tline, '(F10.15)', ADVANCE="no") tline1
end do
where tline should contain your number at the end of the loop.
Because of the record-based I/O, a READ statement will typically throw out what is after the end of the record. But the ADVANCE=no tells it not to.
If you know exactly at what position the value you want starts, you can use the T edit descriptor to initiate the next read from that position.
Let's say, for instance, that the width of each field is 10 characters and you want to read the fifth value. The read statement will then look something like the following.
read(file_unit, '(t41, f10.5)') value1
P.s.: You can dynamically create a format string at runtime, with the correct number after the t, by using a character variable as format and use an internal file write to put in this number.
Let's say you want the value that starts at position n. It will then look something like this (I alternated between single and double quotes to try to make it more clear where each string starts and stops):
write(my_format, '(a, i0, a)') "(t", n, ', f10.5)'
read(file_unit, my_format) value1
I've a question about Fortran 77 and I've not been able to find a solution.
I'm trying to store an array of strings defined as the following:
character matname(255)*255
Which is an array of 255 strings of length 255.
Later I read the list of names from a file and I set the content of the array like this:
matname(matcount) = mname
EDIT: Actually mname value is hardcoded as mname = 'AIR' of type character*255, it is a parameter of a function matadd() which executes the previous line. But this is only for testing, in the future it will be read from a file.
Later on I want to print it with:
write(*,*) matname(matidx)
But it seems to print all the 255 characters, it prints the string I assigned and a lot of garbage.
So that is my question, how can I know the length of the string stored?
Should I have another array with all the lengths?
And how can I know the length of the string read?
Thanks.
You can use this function to get the length (without blank tail)
integer function strlen(st)
integer i
character st*(*)
i = len(st)
do while (st(i:i) .eq. ' ')
i = i - 1
enddo
strlen = i
return
end
Got from here: http://www.ibiblio.org/pub/languages/fortran/ch2-13.html
PS: When you say: matname(matidx) it gets the whole string(256) chars... so that is your string plus blanks or garbage
The function Timotei posted will give you the length of the string as long as the part of the string you are interested in only contains spaces, which, if you are assigning the values in the program should be true as FORTRAN is supposed to initialize the variables to be empty and for characters that means a space.
However, if you are reading in from a file you might pick up other control characters at the end of the lines (particularly carriage return and/or line feed characters, \r and/or \n depending on your OS). You should also toss those out in the function to get the correct string length. Otherwise you could get some funny print statements as those characters are printed as well.
Here is my version of the function that checks for alternate white space characters at the end besides spaces.
function strlen(st)
integer i,strlen
character st*(*)
i = len(st)
do while ((st(i:i).eq.' ').or.(st(i:i).eq.'\r').or.
+ (st(i:i).eq.'\n').or.(st(i:i).eq.'\t'))
i = i - 1
enddo
strlen = i
return
end
If there are other characters in the "garbage" section this still won't work completely.
Assuming that it does work for your data, however, you can then change your write statement to look like this:
write(*,*) matname(matidx)(1:strlen(matname(matidx)))
and it will print out just the actual string.
As to whether or not you should use another array to hold the lengths of the string, that is up to you. the strlen() function is O(n) whereas looking up the length in a table is O(1). If you find yourself computing the lengths of these static strings often, it may improve performance to compute the length once when they are read in, store them in an array and look them up if you need them. However, if you don't notice the slowdown, I wouldn't worry about it.
Depending on the compiler that you are using, you may be able to use the trim() intrinsic function to remove any leading/trailing spaces from a string, then process it as you normally would, i.e.
character(len=25) :: my_string
my_string = 'AIR'
write (*,*) ':', trim(my_string), ':'
should print :AIR:.
Edit:
Better yet, it looks like there is a len_trim() function that returns the length of a string after it has been trimmed.
intel and Compaq Visual Fortran have the intrinsic function LEN_TRIM(STRING) which returns the length without trailing blanks or spaces.
If you want to suppress leading blanks or spaces, use "Adjust Left" i.e. ADJUSTF(STRING)
In these FORTRANs I also note a useful feature: If you pass a string in to a function or subroutine as an argument, and inside the subroutine it is declared as CHARACTER*(*), then
using the LEN(STRING) function in the subroutine retruns the actual string length passed in, and not the length of the string as declared in the calling program.
Example:
CHARACTER*1000 STRING
.
.
CALL SUBNAM(STRING(1:72)
SUBROUTINE SYBNAM(STRING)
CHARACTER*(*) STRING
LEN(STRING) will be 72, not 1000