Inaccessible resource - c

I'm working through Petzold "Programming Windows" 5th edition, using Visual Studio 2015 Community Edition on a Windows 8.1 machine, and having problems with the PoePoem program on p. 432-437.
The program will compile, but throws an exception on execution.
Apparently, in the WM_CREATE message processing, while I can load the text of the poem as a resource and count the number of lines, the debugger reports an access violation in the last line of this code snippet when I attempt to write a '\0' character in place of the backslash '\\'.
Evidently things have changed sufficiently in 20 years that the program as written no longer works. Is there a workaround?
hResource = LoadResource (hInst,
FindResource (hInst, TEXT ("AnnabelLee"),
TEXT ("TEXT"))) ;
pText = (char *) LockResource (hResource) ;
iNumLines = 0 ;
while (*pText != '\\' && *pText != '\0')
{
if (*pText == '\n')
iNumLines ++ ;
pText = AnsiNext (pText) ;
}
*pText = '\0' ;
I had a long wrestle with Visual Studio to get proper construction of the *.rc files and resource.h files, omitted the hInst declaration, misspelled the text several times. I finally got the program to compile, but I'm still missing something.

Related

VS2010, scanf, strange behaviour

I'm converting some source from VC6 to VS2010. The code is written in C++/CLI and it is an MFC application. It includes a line:
BYTE mybyte;
sscanf(source, "%x", &mybyte);
Which is fine for VC6 (for more than 15 years) but causing problems in VS2010 so I created some test code.
void test_WORD_scanf()
{
char *source = "0xaa";
char *format = "%x";
int result = 0;
try
{
WORD pre = -1;
WORD target = -1;
WORD post = -1;
printf("Test (pre scan): stack: pre=%04x, target=%04x, post=%04x, sourse='%s', format='%s'\n", pre, target, post, source, format);
result = sscanf(source, format, &target);
printf("Test (post scan): stack: pre=%04x, target=%04x, post=%04x, sourse='%s', format='%s'\n", pre, target, post, source, format);
printf("result=%x", result);
// modification suggested by Werner Henze.
printf("&pre=%x sizeof(pre)=%x, &target=%x, sizeof(target)=%x, &post=%x, sizeof(post)=%d\n", &pre, sizeof(pre), &target, sizeof(target), &post, sizeof(post));
}
catch (...)
{
printf("Exception: Bad luck!\n");
}
}
Building this (in DEBUG mode) is no problem. Running it gives strange results that I cannot explain. First, I get the output from the two printf statemens as expected. Then a get a run time waring, which is the unexpected bit for me.
Test (pre scan): stack: pre=ffff, target=ffff, post=ffff, source='0xaa', format='%x'
Test (post scan): stack: pre=ffff, target=00aa, post=ffff, source='0xaa', format='%x'
result=1
Run-Time Check Failure #2 - Stack around the variable 'target' was corrupted.
Using the debugger I found out that the run time check failure is triggered on returning from the function. Does anybody know where the run time check failure comes from? I used Google but can't find any suggestion for this.
In the actual code it is not a WORD that is used in sscanf but a BYTE (and I have a BYTE version of the test function). This caused actual stack corruptions with the "%x" format (overwriting variable pre with 0) while using "%hx" (what I expect to be the correct format) is still causing some problems in overwriting the lower byte of variable prev.
Any suggestion is welcome.
Note: I edited the example code to include the return result from sscanf()
Kind regards,
Andre Steenveld.
sscanf with %x writes an int. If you provide the address of a BYTE or a WORD then you get a buffer overflow/stack overwrite. %hx will write a short int.
The solution is to have an int variable, let sscanf write to that and then set your WORD or BYTE variable to the read value.
int x;
sscanf("%x", "0xaa", x);
BYTE b = (BYTE)x;
BTW, for your test and the message
Run-Time Check Failure #2 - Stack around the variable 'target' was corrupted.
you should also print out the addresses of the variables and you'll probably see that the compiler added some padding/security check space between the variables pre/target/post.

c doesn't print "┌──┐" character correctly

Good afternoon, I'm facing a problem on my c code and I don't know what is causing it.
Every time I try to print characters like these: "┌──┐" my program simply prints some strange characters, like on this screenshot:
I'm using Qt Creator on Windows, with Qt version 5.5.0 MSVC 64 bits. The compiler is the Microsoft Visual C++ Compiler 12.0 (amd64).
I tried changing the locale but with no success. The only way I found to print these characters was to define them as int variables with the ASCII code and printing them, but it led to some really extensive and ugly coding, like this:
int cSupEsq = 218; //'┌'
int cSupDir = 191; //'┐'
int cInfEsq = 192; //'└'
int cInfDir = 217; //'┘'
int mVert = 179; //'│'
int mHor = 196; //'─'
int espaco = 255; //' '
int letraO = 111; //'o'
//Inicia limpando a tela da aplicação
clrscr();
//Linha 1
printf("%c", cSupEsq);
for (i = 1; i < 79; i++) { printf("%c", mHor); }
printf("%c", cSupDir);
Is there any way I can make the program treat these characters correctly? What could be causing this problem?
Your solution to use the OEM code points is the right way to go, codepage 850/437 is the default code page for the console and therefore should work. You could also use SetConsoleOutputCP to ensure the correct code page is used for the console.
Having said that, what is happening when you do not use your workaround is that the source file is being saved using a different codepage ie. not codepage 850/437. The in memory representation of the source code is Unicode (probably UTF-8), when you save the file the in memory representation of the characters are mapped to the target code page for the file.
What you can do is to save the file using the 850/437 codepage as the target, I don't know how you do this in Qt Creator (If you can at all), in Visual Studio for example you can select the down arrow on the Save button and select "Save with encoding", you can then proceed to select the target codepage, in your case code page 850. This will ensure that the in memory code points are mapped correctly to the file to be compiled.
I hope that helps explain the issue.
It shouldn't be necessary to print the characters one at a time. Instead, you can use an escape sequence:
printf("\xDA\xBF\xC0\xD9\xB3\xC4\xFF");

error: stray '\302' in program

I have the following piece of code (kernel code to be more specific) :
static int is_sram_locked(void)
{
if (OMAP2_DEVICE_TYPE_GP == omap_type()) {
/* RAMFW: R/W access to all initiators for all qualifier sets */
if (cpu_is_omap242x()) {
__raw_writel(0xFF, OMAP24XX_VA_REQINFOPERM0); /* all q-vects */
__raw_writel(0xCFDE, OMAP24XX_VA_READPERM0); /* all i-read */
__raw_writel(0xCFDE, OMAP24XX_VA_WRITEPERM0); /* all i-write */
}
if (cpu_is_omap34xx() && !cpu_is_am33xx()) {
__raw_writel(0xFFFF, OMAP34XX_VA_REQINFOPERM0); /* all q-vects */
__raw_writel(0xFFFF, OMAP34XX_VA_READPERM0); /* all i-read */
__raw_writel(0xFFFF, OMAP34XX_VA_WRITEPERM0); /* all i-write */
__raw_writel(0x0, OMAP34XX_VA_ADDR_MATCH2);
__raw_writel(0xFFFFFFFF, OMAP34XX_VA_SMS_RG_ATT0);
}
return 0;
} else
return 1; /* assume locked with no PPA or security driver */
}
This is copy-pasted from sublime 3, and as the title states, I get the following compilation error :
error: stray '\302' in program
error: stray '\273' in program
On lines that start with __raw_writel( ... )
I have done research about the problem and I found out that this error tells me that there is an unprintable character on the line in cause.
'\302 \273' is UTF-8 code for '»' (RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK)
I read that this problem often appears when you copy-paste code from somewhere else and those unprintable characters may have skipped your attention or your keyboard has a different layout that types strange characters. I inspected the code very closely and I could not find any of those foreign characters.
My big question is how can kernel code that I have never touched can present such errors ? And I have more than one file that comes with this error, which brings me to the fact that there might be something else wrong.
I have figured it out that I get this error on lines that start with anything else but a letter such as : '_' and '.' (these are the examples that rise issues for me so far)
Solutions I have tried :
Re-writing the entire lines;
Copy-paste the code into many UTF-8 unprintable character filters so I can find the 'stray' characters
Unicode Character Highlighter sublime packages
Note: I'm also using vim as editor and my .vimrc puts '»' as TABS and '·' as SPACES but only for indentation purposes, not as actual characters. I've fixed some similar errors when I copy-pasted from vim and those characters were actually in text, I deleted the characters and it got fixed. But for this I can't identify any 'stray' characters present in the code.
I'm out of ideas I can try to get over this so I'm asking for your help.
The macros were the problem. They referred to some macros I modified with some copy-paste code and completely forgot about it.
Special thanks to all.

Justifying text in C and general array

I'm attempting to fully justify (left and right columns line-up) input from files and this is what I came up with. The input files have embedded commands so from my pseudo output below I start justifying at the company's line and end at telephone As you can see it randomly joins two of the lines read together. Can someone please tell me why it's doing this? My input files definitely have newline characters in them since I double checked they were entered.
Also how do I do the following: Check if my read line will fit into my output array (of 40 char)? If it doesn't I want to move the overflowed string(s) into the next line or char(s) if it's easier. This one isn't as necessary as my first question but I would really like to make the output as nice as possible and I don't know how to restrict and carry overflow from read lines into the next output array.
Since it began to escape from AT&T's Bell Laboratories in
the early 1970's, the success of the UNIX
operating system has led to many different
versions: recipients of the (at that time free) UNIX system
code all began developing their own different
versions in their own different ways for use and sale.
Universities, research
institutes, government bodies and computer
companies all began using the powerful
UNIX system to develop many of the
technologies which today are part of a
UNIX system. Computer aided design,
manufacturing control systems,laboratorysimulations,even the Internet itself,
all began life with and because of UNIX
Today, without UNIX systems, the Internewould come to a screeching halt.
Most telephone calls could not be made,
electronic commerce would grind to a halt and
there would have never been "Jurassic Park"!
Below is my justify function that's passed the read file line using fgets in another function. The printf lines are just for debugging.
void justify(char strin[]){
int i = 0; //strin iterator
int j = 0; //out iterator
int endSpaces = LINE + 1 - strlen(strin);
int voids = countwords(strin) - 1;
printf("Voids: %d\n", voids);
printf("Input: %s", strin);
//No words in line, exit
if (voids <= 0)
return;
//How many to add between words
int addEvenly = endSpaces/voids;
int addUnevenly = endSpaces % voids;
printf("space to distribute: %d evenly: %d unevenly: %d\n", endSpaces, addEvenly, addUnevenly);
//Copy space left of array to output
while (strin[i] == ' '){
outLine[j++] = ' ';
i++;
}
//One word at a time
while (endSpaces > 0 || addUnevenly > 0){
//Copy letters into out
while (strin[i] != ' '){
outLine[j] = strin[i];
i++;
j++;
}
//Add the necessary spaces between words
if (addEvenly > 0){
for (int k = 0; k < addEvenly; k++){
outLine[j++] = ' ';
}
}
//Distribute to the left
if (addUnevenly > 0){
outLine[j++] = ' ';
endSpaces--;
addUnevenly--;
}
printf("Output: %s\n\n", outLine);
endSpaces = endSpaces - addEvenly;
//Finish copying rest of input to output when no more spaces to add
if (endSpaces == 0 && addUnevenly == 0){
while (strin[i] != '\0')
outLine[j++] = strin[i++];
printf("Output 2: %s\n", outLine);
}
}
fprintf(out, "%s", outLine);
}
On sunday I created a function (justifyline()) able to justify and indent a line you give it as input. It outputs a buffer containing the justified (formatted) text and any eventual text-remainder; such a remainder may be used as input to the function justifyline().
After this step I've used the file below (text.txt) to test the behaviour of such a function. That test demonstrates me the need to use also word wrapping between lines. Then I've written the function formatLineByLine(). The function formatLineByLine() doesn't care of void lines.
Text file (text.txt): (I used the text in your question trying to correct it, but not all I've corrected, then the input file suffers of this fact!)
Since it began to escape from AT&T's
Bell Laboratories in the early 1970's,
the success of the UNIX operating system
has led to many different versions:
recipients of the (at that time free)
UNIX system code all began developing
their own different versions in their
own different ways for use and sale.
Universities, research institutes,
government bodies and computer companies
all began using the powerful UNIX system
to develop many of the technologies which
today are part of a UNIX system.
Computer aided design, manufacturing
control systems, laboratory simulations,
even the Internet itself, all began life
with and because of UNIX Today, without
UNIX systems, the Internet would come to a
screeching halt. Most telephone calls
could not be made, electronic commerce
would grind to a halt and there would
have never been "Jurassic Park"!
The output of the function formatLineByLine()
ABCDE12345678901234567890123456789012345
Since it began to escape from
AT&T's Bell Laboratories in the
early 1970's, the success of the
UNIX operating system has led to
many different versions: recipients
of the (at that time free) UNIX
system code all began developing
their own different versions in
their own different ways for use
and sale. Universities, research
institutes, government bodies and
computer companies all began using
the powerful UNIX system to develop
many of the technologies which
today are part of a UNIX system.
Computer aided design,
manufacturing control systems,
laboratory simulations, even the
Internet itself, all began life
with and because of UNIX Today,
without UNIX systems, the Internet
would come to a screeching halt.
Most telephone calls could not be
made, electronic commerce would
grind to a halt and there would
have never been "Jurassic Park"!
Another step is the idea to use a paragraph per paragraph justifycation. Then I've written the function justifyParagraph(). The function formatInParagraphs() reads the file text.txt and prints it justified using the function justifyParagraph().
The output of the function formatInParagraphs()
ABCDE12345678901234567890123456789012345
Since it began to escape from
AT&T's Bell Laboratories in the
early 1970's, the success of the
UNIX operating system has led to
many different versions: recipients
of the (at that time free) UNIX
system code all began developing
their own different versions in
their own different ways for use
and sale.
Universities, research
institutes, government bodies and
computer companies all began using
the powerful UNIX system to develop
many of the technologies which
today are part of a UNIX system.
Computer aided design,
manufacturing control systems,
laboratory simulations, even the
Internet itself, all began life
with and because of UNIX Today,
without UNIX systems, the Internet
would come to a screeching halt.
Most telephone calls could not be
made, electronic commerce would
grind to a halt and there would
have never been "Jurassic Park"!
The function justifyline() is able to create a justified buffer with indentation (parameter size_t indent) and to use also a single space between the words (parameter int nospacing sent as 1).
The function justifyParagraph() is able to create a justified buffer with line indentation (parameter: size_t indent) and 1st line indentation (parameter: size_t indentstart). The formatted output may be directly printed when a NULL output buffer is sent to the function (parameter char **outbuf sent as NULL). The last line the function generates may be justified or not (parameter: int notFrmtLast sent as 1).
Both justification functions, when the parameter char **outbuf points a NULL pointer ( *outbuf == NULL ), allocate memory using malloc() . In this case you have to free the buffer after its use. If this parameter is passed as NULL to the function justifyParagraph(), the function prints the elaborated output, if outbuf is passed as NULL to the function justifyline(), the function returns an error.
The code is below. An issue of this code is that, in some cases, the length of the string should be computed using a function different from strlen(). To avoid this problem you may use these functions with lines that have a single space between the words. Such a problem affects the functions justifyParagraph() and formatLineByLine().
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int justifyLine(char *inbuf, char **outbuf, size_t linelen, char ** endptr, size_t indent, int nospacing);
int justifyParagraph(char *inbuf,char **outbuf,size_t linelen,size_t indentstart,size_t indent,int notFmtLast);
int formatLineByLine(FILE *f, size_t linelen,size_t indent, int notFrmtLast);
int formatInParagraphs(FILE *f, size_t linelen,size_t indentstart,size_t indent, int notFrmtLast);
int justifyParagraph(char *inbuf,char **outbuf,size_t linelen,size_t indentstart,size_t indent,int notFmtLast)
{
char *optr=NULL,*endp=NULL;
size_t len,s;
int retval,nf;
for(;;) { //Error control loop
if (inbuf==NULL) {
retval=0x10;break;
}
if (indent+indentstart>linelen) {
retval=0x20;break;
}
if (outbuf!=NULL) {
if (*outbuf==NULL) {
if ( (*outbuf=malloc(linelen+1))==NULL ){
retval=0x30;break;
}
}
optr=*outbuf;
}
endp=inbuf;
indent+=indentstart;
len=linelen-indent;
s=indentstart;nf=0;
while( *endp!=0) {
if (notFmtLast && strlen(endp)<linelen-indent)
nf=1;
if ( (retval=justifyLine(endp,&optr,linelen,&endp,
indent,nf)) ) {
retval|=0x40;break;
}
if (outbuf!=NULL) {
optr+=strlen(optr);
*optr++='\n';
*optr=0;
} else {
puts(optr);
}
indent-=s;
len+=s;
s=0;
}
break; //Close error ctrl loop!
}
if (outbuf==NULL && optr!=NULL)
free(optr);
return retval;
}
int justifyLine(char *inbuf,char **outbuf,size_t linelen, char ** endptr,size_t indent,int nospacing)
{
size_t textlen,tmp;
size_t spctoadd,spcodd,spcin;
size_t timetoodd;
size_t ibidx,obidx,k,wc;
char * endp;
char * outb=NULL;
int retval=0;
for(;;) { //Error control loop
endp=inbuf;
if (inbuf==NULL) {
retval=1;break;
}
if (indent>linelen) {
retval=2;break;
}
if (outbuf==NULL) {
retval=3;break;
}
if (*outbuf==NULL) {
if ( (*outbuf=malloc(linelen+1))==NULL ){
retval=4;break;
}
}
outb=*outbuf;
//Leave right spaces
while(*inbuf==' ')
inbuf++;
if (*inbuf==0) {
endp=inbuf;
*outb=0;
break; //exit from error loop without error!
}
linelen-=indent;
//Count words and the minimum number of characters
ibidx=0;
wc=0;textlen=0;k=1;endp=NULL;
while ( *(inbuf+ibidx)!=0 ) {
if (*(inbuf+ibidx)==' ') {
ibidx++;continue;
}
//There's a char!
k=ibidx; //last word start
tmp=textlen;
wc++;textlen++; //add the space after the words
//textlen<linelen because textlen contains also the space after the word
// while(textlen<=linelen && *(inbuf+ibidx)!=' ' && *(inbuf+ibidx) ) {
while(*(inbuf+ibidx)!=' ' && *(inbuf+ibidx) ) {
textlen++;ibidx++;
}
if (textlen>linelen+1) {
endp=inbuf+k;
textlen=tmp;
wc--;
break;
}
}
textlen=textlen-wc;
if (endp==NULL) {
endp=inbuf+ibidx;
}
if (textlen<2) {
*outb=0;
break; //exit from error loop without error!
}
//Prepare outbuf
memset(outb,' ',linelen+indent);
*(outb+linelen+indent)=0;
ibidx=0;
obidx=indent;
if (wc>1) {
if (!nospacing) {
//The odds are max in number == wc-2
spctoadd=linelen-textlen;
} else {
spctoadd=wc-1;
}
spcin=spctoadd/(wc-1);
spcodd=spctoadd % (wc-1);
if (spcodd)
timetoodd=(wc-1)/spcodd;
k=timetoodd;
while(spctoadd) {
while(*(inbuf+ibidx)!=' ') {
*(outb+obidx++)=*(inbuf+ibidx++);
}
obidx+=spcin;spctoadd-=spcin;
if (spcodd && !(--k)) {
k=timetoodd;
spcodd--;
spctoadd--;
obidx++;
}
while(*(inbuf+ ++ibidx)==' ');
}
}
while(*(outb+obidx) && *(inbuf+ibidx) && *(inbuf+ibidx)!=' ')
*(outb+obidx++)=*(inbuf+ibidx++);
//There're words longer then the line!!!
if (*(inbuf+ibidx) && *(inbuf+ibidx)!=' ')
endp=inbuf+ibidx;
break; //Terminate error ctrl loop.
}
if (endptr!=NULL)
*endptr=endp;
return retval;
}
int formatLineByLine(FILE *f, size_t linelen,size_t indent, int notFrmtLast)
{
char text[250],*app;
//justifyLine allocates memory for the line if the outbuf (optr) value is NULL
char * optr=NULL;
size_t j,k;
//print a ruler
for(j=0;j<indent;j++)
printf("%c",'A'+(char)j);
for(j=1;j<=linelen-indent;j++)
printf("%c",'0'+(char)(j%10));
printf("\n");
//starts printing
fseek(f,0,SEEK_SET);
j=0;
while(fgets(text+j,sizeof(text)-j,f)) {
if ( (app=strrchr(text+j,'\n')) ) {
*app=0;
}
k=strlen(text);
if (strlen(text)<linelen-indent) {
if (!*(text+k) && *(text+k-1)!=' ') {
*(text+k++)=' ';
*(text+k)=0;
}
j=k;
continue;
}
app=text;
do {
//justifyLine allocates memory for the line if the outbuf (optr) value is NULL
if ( justifyLine(app,&optr,linelen,&app,indent,0) ) {
if (optr!=NULL)
free(optr);
return 1;
}
printf("%s\n",optr);
j=(*app!=0)?strlen(app):0;
} while(j>linelen-indent);
if (j) {
strcpy(text,app);
*(text+j++)=' ';
*(text+j)=0;
}
}
if (*text!=0 && j) {
if ( justifyLine(text,&optr,linelen,NULL,indent,notFrmtLast) )
{
if (optr!=NULL)
free(optr);
return 2;
}
printf("%s\n",optr);
}
//justifyLine allocates memory for the line if the outbuf value is NULL
if (optr!=NULL)
free(optr);
return 0;
}
int formatInParagraphs(FILE *f, size_t linelen,size_t indentstart,size_t indent, int notFrmtLast)
{
char text[1024], *app;
//To uncomment when you use the commented justifyParagraph line.
//see below
//char *outbuf=NULL;
size_t j;
//print a ruler
for(j=0;j<indent;j++)
printf("%c",'A'+(char)j);
for(j=1;j<=linelen-indent;j++)
printf("%c",'0'+(char)(j%10));
printf("\n");
//starts printing
fseek(f,0,SEEK_SET);
j=0;
while(fgets(text+j,sizeof(text),f)) {
if ( (app=strrchr(text+j,'\n')) ) {
*app++=' ';*app=0;
}
if ( *(text+j)==' ' && !*(text+j+1) ) {
//The following commented line allocates memory creating a paragraph buffer!
//doesn't print the formatted line.
//justifyParagraph(text,&outbuf,linelen,indentstart,indent,notFrmtLast);
//This line directly print the buffer allocating and de-allocating
//only a line buffer. It prints the formatted line.
justifyParagraph(text,NULL,linelen,indentstart,indent,notFrmtLast);
j=0;
//To uncomment when you use the commented justifyParagraph line.
// printf("%s\n\n",outbuf);
puts("");
} else {
j+=strlen(text+j);
}
}
return 0;
}
int main(void)
{
FILE * file;
file=fopen("text.txt","r");
formatLineByLine(file,40,5,1);
puts("");
formatInParagraphs(file,40,5,5,1);
fclose(file);
return 0;
}
You were incredibly close – but you forgot one thing!
After copying a word into outLine, you insert the correct number of additional spaces, and continue with 'the next word'. However, at that point the input pointer i still is at the end of the previously copied word (so it points to the first space immediately after that). The test while (strin[i] != ' ') then immediately fails and you insert the additional spaces at that point again. This continues until you run out of spaces to add, and at the very end you add what was not processed, which is "the entire rest of the string".
The fix is simple: after copying your word into outLine, copy the original space(s) as well, so the i iterator gets updated to point to the next word.
//One word at a time
while (endSpaces > 0 || addUnevenly > 0)
{
//Copy letters into out
while (strin[i] != ' ')
{
outLine[j] = strin[i];
i++;
j++;
}
//Copy original spaces into out <-- FIX!
while (strin[i] == ' ')
{
outLine[j] = strin[i];
i++;
j++;
}
With this, your code works entirely as you intended. Output:
|Since it began to escape from AT&T's Bell Laboratories in|
|the early 1970's, the success of the UNIX|
|operating system has led to many different|
|versions: recipients of the (at that time free) UNIX system|
|code all began developing their own different|
|versions in their own different ways for use and sale.|
| Universities, research|
|institutes, government bodies and computer|
|companies all began using the powerful |
|UNIX system to develop many of the |
|technologies which today are part of a |
|UNIX system. Computer aided design, |
|manufacturing control systems,laboratorysimulations,even the Internet itself, |
|all began life with and because of UNIX |
|Today, without UNIX systems, the Internewould come to a screeching halt.|
|Most telephone calls could not be made,|
|electronic commerce would grind to a halt and|
|there would have never been "Jurassic Park"! |
Possible improvements
Justified lines should never begin with whitespace (your Copy space left of array to output part). Just increment the pointer there:
//Copy space left of array to output
while (strin[i] == ' ')
{
// outLine[j++] = ' ';
i++;
endSpaces++;
}
(and move the calculation for How many to add between words below this, because it changes endSpaces).
The same goes for spaces at the end. You can adjust endSpaces at the start
int l = strlen(strin);
while (l > 0 && strin[l-1] == ' ')
{
l--;
endSpaces++;
}
and suppress copying the trailing spaces into outLn at the bottom. (That needs some additional tinkering, I couldn't get it right first time.)
It is much neater to ignore multiple spaces inside the input string as well, but that takes a bit more code.
With these three implemented, you get a slightly neater output:
|Since it began to escape from AT&T's Bell Laboratories in|
|the early 1970's, the success of the UNIX|
|operating system has led to many different|
|versions: recipients of the (at that time free) UNIX system|
|code all began developing their own different|
|versions in their own different ways for use and sale.|
|Universities, research|
|institutes, government bodies and computer|
|companies all began using the powerful|
|UNIX system to develop many of the|
|technologies which today are part of a|
|UNIX system. Computer aided design,|
|manufacturing control systems,laboratorysimulations,even the Internet itself,|
|all began life with and because of UNIX|
|Today, without UNIX systems, the Internewould come to a screeching halt.|
|Most telephone calls could not be made,|
|electronic commerce would grind to a halt and|
|there would have never been "Jurassic Park"!|
A drawback of this one-line-at-a-time method is that it cannot easily be rewritten to gather input until a line overflows. To do so, you need:
a routine that skips all spaces and return a pointer to the next word.
a routine that reads words until a line is 'overfull' – that is, the number of words plus (the number of words - 1) for spaces is larger than your LINE value. This uses routine #1 and outputs exactly one justified line.
You need to pass on the location and number of strings from your main to both these routines, and in both check if you are at the end of either a single input line or the entire input array.
I've written this main that contains two simple methods to center a text in a line. The first method only prints the text variable without modifying it, the second method modifies the text variable and then prints it. (Here method is not intended as function, the code contains two examples which you may translate easily in simple functions)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
char text[81],fmt[10];
int linelen=80,tlen;
int spacetocenter=0;
printf("Insert text to center [max %lu char]:\n",sizeof(text)-1);
if (scanf("%[^\n]",text)<1) {
perror("scanf");
return -1;
}
getchar(); //Leaves return from the buffer
tlen=strlen(text);
spacetocenter=(linelen-tlen)/2;
if (spacetocenter<0)
spacetocenter=0;
//Method one (this doesn't modify text)
//This method directly prints the contents of text centered.
//----------------------------------------------------------
snprintf(fmt,sizeof(fmt),"%%%+ds\n",spacetocenter+tlen);
//printf("%s\n",fmt); // prints the used format
printf(fmt,text);
//Method two (this modifies text)
//This method modifies the contents of the variable text
//----------------------------------------------------------
memmove(text+spacetocenter,text,tlen+1);
memset(text,' ',spacetocenter);
printf("%s\n",text);
return 0;
}
Note:
After the second method is applied tlen no longer contains the length of text!
The program consider the line of 80 chars, if you need shorter/longer lines you have to modify the value of the variable linelen.

fscanf bus error: 10 when switching from Snow Leopard to Lion

First off, this snippet is not meant for production code. So please, no lecturing about it "being unsafe." Thanks!
So, the following code is part of a parser that takes in a csv and uses it to populate an sqlite3 db. When compiled and ran in Snow Leopard, it worked just fine. Now that I've switched to Lion, the scanf statement throws Bus Error: 10. Specifically, it seems to have something to do with how I am consuming and discarding the '\n' at the end of each line:
int main()
{
sqlite3* db;
sqlite3_open("someExistingDB.sqlite3", &db);
FILE *pFile;
pFile = fopen("excelData.csv","r");
char name[256],country[256], last[256], first[256], photoURI[256];
char sqlStatement[16384];
while(fscanf(pFile, "%[^,],%[^,],%[^,],%[^,],%[^\n]%*c", name, country, last,first, photoURI) != EOF)
{
blah...
...
if I remove the last %*c, which is meant to consume the '\n' and ignore it so as to advance to the next line, the program does not crash. But of course does an incorrect parsing.
Also, mind you, the EOF doesn't seem to be the problem; I'e also tried a single fscanf statement instead of the while-loop shown above.
Any thoughts?
EDIT: Let me add that the code was originally compiled and ran in an intel core duo (32-bit) macbook with Snow Leopard and now I am compiling it and running it on a MacPro (64-bit) with Lion. So I wonder if it might have something to do with alignment?
Interesting. Bus errors are usually due to alignment issues but that may not be the case here since all you're scanning in is chars.
One thing you may want to consider is to fgets the entire line into a buffer and the sscanf it. This will allow you to do two things:
print out the line in a debug statement before sscanfing it (or after scanning, if the expected conversion count is wrong), so you can see if there are any problems; and
not worry about trying to align the line-ending with fscanf, since fgets does a good job of this already.
So it would be something like (untested):
char bigHonkinBuffer[16384];
while (fgets (bigHonkinBuffer, sizeof(bigHonkinBuffer), pFile) != NULL) {
if (sscanf(bigHonkinBuffer, "%[^,],%[^,],%[^,],%[^,],%[^\n]", name, country, last,first, photoURI) != 5) {
// printf ("Not scanned properly: [%s]\n", bigHonkinBuffer);
exit (1);
}
}
You should also check the return values from the sqlite3_open and fopen calls, if this is anything more than "play" code (i.e., if there's the slightest possibility that those files may not exist).
I tried the following adaptation of your code on a Mac Mini running Lion (10.7.1) with XCode 4.
#include <stdio.h>
static void print(const char *tag, const char *str)
{
printf("%8s: <<%s>>\n", tag, str);
}
int main(void)
{
FILE *pFile = fopen("excelData.csv","r");
char name[256], country[256], last[256], first[256], photoURI[256];
while (fscanf(pFile, "%[^,],%[^,],%[^,],%[^,],%[^\n]%*c",
name, country, last, first, photoURI) == 5)
{
print("name", name);
print("country", country);
print("last", last);
print("first", first);
print("photoURI", photoURI);
}
return 0;
}
I produced a 64-bit binary using:
gcc -O -std=c99 -Wall -Wextra xxx.c -o xxx
There were no warnings of any sort. Given the input data:
Monster,United States,Smith,John,http://www.example.com/photo1
Emancipated Majority,Canada,Jones,Alan,http://www.example.com/photo2
A Much Longer Name Than Any Before,A Land from Far Away and In the Imagination Most Beautiful,OneOfTheLongerFamilyNamesYou'llEverSee,ALongishGivenName,http://www.example.com/photo3/elephant/pygmalion/photo3,x31
It produces the output:
name: <<Monster>>
country: <<United States>>
last: <<Smith>>
first: <<John>>
photoURI: <<http://www.example.com/photo1>>
name: <<Emancipated Majority>>
country: <<Canada>>
last: <<Jones>>
first: <<Alan>>
photoURI: <<http://www.example.com/photo2>>
name: <<A Much Longer Name Than Any Before>>
country: <<A Land from Far Away and In the Imagination Most Beautiful>>
last: <<OneOfTheLongerFamilyNamesYou'llEverSee>>
first: <<ALongishGivenName>>
photoURI: <<http://www.example.com/photo3/elephant/pygmalion/photo3,x31>>
The != EOF vs == 5 change does not matter with the sample data, but is arguably more robust in general. The last line of data exploits your change in pattern and contains a comma in the 'last field'.
Since your code does not check that the file was opened correctly, I have to wonder whether that is your problem, though that's more likely to produce a segmentation violation than a bus error.
So, no answer to your problem - but some code for you to try.

Resources