Ok, so I have a text file filled with student numbers and the corresponding name. I want to get all those data, format them properly (uppercase, proper number of spaces, etc.) and put them in another file. The original text format is somewhat like this:
20111101613 XXXXXXXX , XXXX
20111121235 xxXXXX, xxxxxx
20111134234 XXXX, XxxX
20111104142 XXXXXxxxX, XXXX
20111131231 XX , XXXXXX
Example: Input file content is something like this:
20111112346 Zoomba, Samthing
20111122953 Acosta, Arbyn
20110111241 Smith, John
20111412445 Over, Flow Stack
20111112345 foo, BAR
And the output file content should be like this:
20111122953 ACOSTA, ARBYN
20111112345 FOO, BAR
20111412445 OVER, FLOW STACK
20110111241 SMITH, JOHN
20111112346 ZOOMBA, SAMTHING
EDIT: Can someone give me a hint or the solution on how to make this function with using regular expressions?
function sortslist($infile, $outfile)
{
// open the input file named conversion.txt
$inptr = fopen($infile, "r");
if (!$inptr)
{
trigger_error("File cannot be opened: $infile", E_USER_ERROR);
}
// initialize student number to zero
$snum = 0;
// number of letters in the name string
$n = 0;
// initialize the name string to be empty
$name = "";
// iteratively scan the input file
$done = false;
while (!$done)
{
// get each character in the file
$c = fgetc($inptr);
// if the character is a digit, add it to the student number
if (ctype_digit($c))
{
$snum = (($snum * 10) + ($c - '0'));
}
// else, add to name string including commas and space. Input file might have tabs
else if (ctype_alpha($c) || ($n > 0 && ($c == " " || $c == "\t")) || $c == ",")
{
// append the new character to name string
$name .= $c;
// add a space after the comma
if ($c == ",")
{
$name .= " ";
$n++;
}
// increment the number of letters
$n++;
}
// end of the line
else if ($c == "
" || !$c)
{
// 0 is added to student numbers when newline is detected so neglect them
if ($snum != 0 && $name != "
")
{
// replace consecutive spaces with one space only
$name = preg_replace(['/\s\s+/', '/\s,/', '/(\s*)(?>$)/'], [' ', ',', ''], $name);
// record student number and name
$info['snum'][] = $snum;
$info['name'][] = strtoupper($name);
}
// reset the values needed
$snum = 0;
$n = 0;
$name = "";
// if we hit the end of the file then it is done
if (!$c)
{
$done = true;
}
}
}
// sort the students names alphabetically
array_multisort($info['name'], $info['snum']);
// combine the name strings and there corresponding student number
$i = 0;
$students = [];
$last_student = end($info['snum']);
foreach ($info['snum'] as $snum)
{
$students[$snum] = $snum . " " . $info['name'][$i++];
// update input file too
fwrite($inptr, $students[$snum]);
// don't add a newline to the end of the file
if ($snum != $last_student)
{
$students[$snum] .= "
";
}
}
// put it into a new file called slist.txt
file_put_contents($outfile, $students, LOCK_EX);
// close the input file
fclose($inptr);
}
Your problem lies in the fact that $hashtable
values are stored with the student ID first in the string. asort()
will allways look at the beginning of the value, and sort according to that. So in order to sort by the name, you will have to split up the student ID and the name into two separate arrays and then sort them using array_multisort()
.
Replace:
$hashtable[$snum] = $snum . " " . strtoupper($name) . "
";
with:
$snums[] = $snum;
$names[] = strtoupper($name);
array_multisort($names, $snums);
$j = 0;
while ($names) {
$hashtable[$snum] = $snums[$j]. " ". $names[$j]. "
";
$j++;
}